PHP is a very easy
language to learn, and many people without any sort of background in
programming learn it as a way to add interactivity to their web sites.
Unfortunately, that often means PHP programmers, especially those newer to web
development, are unaware of the potential security risks their web applications
can contain. Here are a few of the more common security problems and how to
avoid them.
Rule Number One:
Never, Ever, Trust Your Users
It can never be said
enough times, you should never, ever, ever trust your users to send you the
data you expect. I have heard many people respond to that with something like
"Oh, nobody malicious would be interested in my site". Leaving aside
that that could not be more wrong, it is not always a malicious user who can
exploit a security hole - problems can just as easily arise because of a user
unintentionally doing something wrong.
So the cardinal rule
of all web development, and I can't stress it enough, is: Never, Ever,
Trust Your Users. Assume every single
piece of data your site collects from a user contains malicious code. Always.
That includes data you think you have checked with client-side validation, for
example using JavaScript. If you can manage that, you'll be off to a good
start. If PHP security is important to you, this single point is the most
important to learn. Personally, I have a "PHP Security" sheet next to
my desk with major points on, and this is in large bold text, right at the top.
Global Variables
In many languages you
must explicitly create a variable in order to use it. In PHP, there is an
option, "register_globals", that you can set in php.ini that allows
you to use global variables, ones you do not need to explicitly create.
Consider the following code:-
<pre
name="code" class="html">
if ($password ==
"my_password") {
$authorized = 1;
}
if ($authorized == 1)
{
echo "Lots of important stuff.";
}
</pre>
To many that may look
fine, and in fact this exact type of code is in use all over the web. However,
if a server has "register_globals" set to on, then simply adding
"?authorized=1" to the URL will give anyone free access to exactly what
you do not want everyone to see. This is one of the most common PHP security
problems.
Fortunately, this has
a couple of possible simple solutions. The first, and perhaps the best, is to
set "register_globals" to off. The second is to ensure that you only
use variables that you have explicitly set yourself. In the above example, that
would mean adding "$authorized = 0;" at the beginning of the script:
$authorized = 0;
if ($password == "my_password") {
$authorized = 1;
}
if ($authorized == 1) {
echo "Lots of
important stuff.";
}
Error Messages
Errors are a very
useful tool for both programmer and hacker. A developer needs them in order to
fix bugs. A hacker can use them to find out all sorts of information about a
site, from the directory structure of the server to database login information.
If possible, it is best to turn off all error reporting in a live application.
PHP can be told to do this through .htaccess or php.ini, by setting
"error_reporting" to "0". If you have a development
environment, you can set a different error reporting level for that.
SQL Injection
One of PHP's greatest
strengths is the ease with which it can communicate with databases, most
notably MySQL. Many people make
extensive use of this, and a great many sites, including this one, rely on
databases to function.
However, as you would
expect, with that much power there are potentially huge security problems you
can face. Fortunately, there are plenty of solutions. The most common security hazard
faced when interacting with a database is that of SQL Injection - when a user
uses a security glitch to run SQL queries on your database.
Let's use a common
example. Many login systems feature a line that looks a lot like this when
checking the username and password entered into a form by a user against a
database of valid username and password combinations, for example to control
access to an administration area:
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$_POST['username']."' and Password = '".$_POST[‘password’]."';
Look familiar? It may well do. And on the face of it, the above
does not look like it could do much damage. But let's say for a moment that I
enter the following into the "username" input box in the form and
submit it:
' OR 1=1 #
The query that is going to be executed will now look like this:
SELECT Username, Password FROM Users WHERE Username = '' OR 1=1 #' and Password = ''
The hash symbol (#) tells MySQL that everything following it is
a comment and to ignore it. So it will actually only execute the SQL up to that
point. As 1 always equals 1, the SQL will return all of the usernames and
passwords from the database. And as the first username and password combination
in most user login databases is the admin user, the person who simply entered a
few symbols in a username box is now logged in as your website administrator,
with the same powers they would have if they actually knew the username and
password.
With a little creativity, the above can be exploited further,
allowing a user to create their own login account, read credit card numbers or
even wipe a database clean.
Fortunately, this type of vulnerability is easy enough to work
around. By checking for apostrophes in the items we enter into the database,
and removing or neutralising them, we can prevent anyone from running their own
SQL code on our database. The function below would do the trick:
function make_safe($variable) {
$variable = mysql_real_escape_string(trim($variable));
return $variable;
}
Now, to modify our query. Instead of using _POST variables as in
the query above, we now run all user data through the make_safe function,
resulting in the following code:
$username = make_safe($_POST['username']);
$password = make_safe($_POST['password']);
$check = mysql_query("SELECT Username, Password, UserLevel FROM Users WHERE Username = '".$username."' and Password = '".$password."'");
Now, if a user entered the malicious data above, the query will
look like the following, which is perfectly harmless. The following query will
select from a database where the username is equal to "\' OR 1=1 #".
SELECT Username, Password, UserLevel FROM Users WHERE Username = '\' OR 1=1 #' and Password = ''
Now, unless you happen to have a user with a very unusual
username and a blank password, your malicious attacker will not be able to do
any damage at all. It is important to check all data passed to your database
like this, however secure you think it is. HTTP Headers sent from the user can
be faked. Their referral address can be faked. Their browsers User Agent string
can be faked. Do not trust a single piece of data sent by the user, though, and
you will be fine.
File
Manipulation
Some sites currently running on the web today have URLs that
look like this:
index.php?page=contactus.html
The "index.php" file then simply includes the
"contactus.html" file, and the site appears to work. However, the
user can very easily change the "contactus.html" bit to anything they
like. For example, if you are using Apache's mod_auth to protect files and have saved your password in a
file named ".htpasswd" (the conventional name), then if a user were
to visit the following address, the script would output your username and
password:
index.php?page=.htpasswd
By changing the URL, on some systems, to reference a file on
another server, they could even run PHP that they have written on your site.
Scared? You should be. Fortunately, again, this is reasonably easy to protect
against. First, make sure you have correctly set "open_basedir" in
your php.ini file, and have set "allow_url_fopen" to "off".
That will prevent most of these kinds of attacks by preventing the inclusion of
remote files and system files. Next, if you can, check the file requested
against a list of valid files. If you limit the files that can be accessed
using this script, you will save yourself a lot of aggravation later.
Using
Defaults
When MySQL is installed, it uses a default username of
"root" and blank password. SQL Server uses "sa" as the
default user with a blank password. If someone finds the address of your
database server and wants to try to log in, these are the first combinations
they will try. If you have not set a different password (and ideally username
as well) than the default, then you may well wake up one morning to find your
database has been wiped and all your customers' credit card numbers stolen. The
same applies to all software you use - if software comes with default username
or password, change them.
Leaving
Installation Files Online
Many PHP programs come with installation files. Many of these
are self-deleting once run, and many applications will refuse to run until you
delete the installation files. Many however, will not pay the blindest bit of
attention if the install files are still online. If they are still online, they
may still be usable, and someone may be able to use them to overwrite your
entire site.
Predictability
Let us imagine for a second that your site has attracted the
attention of a Bad Person. This Bad Person wants to break in to your
administration area, and change all of your product descriptions to "This
Product Sucks". I would hazard a guess that their first step will be to go
to http://www.yoursite.com/admin/ - just in case it exists. Placing your
sensitive files and folders somewhere predictable like that makes life for
potential hackers that little bit easier.
With this in mind, make sure you name your sensitive files and
folders so that they are tough to guess. Placing your admin area at
http://www.yoursite.com/jsfh8sfsifuhsi8392/ might make it harder to just type
in quickly, but it adds an extra layer of security to your site. Pick something
memorable by all means if you need an address you can remember quickly, but
don't pick "admin" or "administration" (or your username or
password). Pick something unusual.
The same applies to usernames and passwords. If you have an
admin area, do not use "admin" as the username and
"password" as the password. Pick something unusual, ideally with both
letters and numbers (some hackers use something called a "dictionary
attack", trying every word in a dictionary as a password until they find a
word that works - adding a couple of digits to the end of a password renders
this type of attack useless). It is also wise to change your password fairly
regularly (every month or two).
Finally, make sure that your error messages give nothing away.
If your admin area gives an error message saying "Unknown Username"
when a bad username is entered and "Wrong Password" when the wrong
password is entered, a malicious user will know when they've managed to guess a
valid username. Using a generic "Login Error" error message for both
of the above means that a malicious user will have no idea if it is the
username or password he has entered that is wrong.
Finally,
Be Completely and Utterly Paranoid
If you assume your site will never come under attack, or face
any problems of any sort, then when something eventually does go wrong, you
will be in massive amounts of trouble. If, on the other hand, you assume every
single visitor to your site is out to get you and you are permanently at war,
you will help yourself to keep your site secure, and be prepared in case things
should go wrong.
#Reference https://www.addedbytes.com/
No comments:
Post a Comment