Monday, March 17, 2008

Making Secure PHP Applications

There are 2 basic types of attacks that a cracker will try to gain access you don’t really want him to have. This lesson runs though what the cracker does and how you can fight against. This is really anything but a definitive guide to security, there is no possible way to cover security in a 4 page article. But this is a good start to security. To conclude the introduction, XSS attacks are too broad of a range and wont be covered here.

Generally, scripts that don’t have their source revealed to the public are harder to crack. Scripts which you can get the source from always have to take more precautions. Either way, the same precautions should be taken, not giving the source doesn’t make it uncrackable. Security is extremely important, I learned that when I had a bug in img911’s script that allowed php files to be uploaded. There was a script that gave the uploader full control of my files, the site was only a week old! People will come to your site and try to gain access if they can. It is a matter of time before it happens to you, are you ready?

Attack One: SQL Injection Attacks
What it is
This is by a good margin the most common type of attack because of its shear power, that and its easy to do. SQL injection attacks inject commands via user imputed data that could cause damage to your database.

How it works
SQL injection attacks happen when you modify data that is being sent into a database, for instance
You could change that to
showimage.php?id=1′; DELETE FROM images WHERE 1;
That would create an error for the sql if there is any command passed the WHERE clause, but the DELETE command would run and work. This gives the cracker full control of your database, anything you could do with mysql_query, he can do. He doesnt just have to use get data, he can use POST data that is being sent from a form, he can also edit cookies that the site uses.

How to prevent
There are a few ways to prevent an SQL attack.

Method 1, Clean the data
The first way is to strip slashes, quotes and other things that have no legit purpose in the query. THIS IS NECESSARY IN ANYTHING THAT IS USER INPUTED AND WILL BE USED WITH A DATABASE! User inputted data is anything that can be edited from the outside, GET data (.php?getdata=data), user inputted POST data and cookies can all be edited by a user. Anything coming from those must be cleaned or your script is not safe. I use this function to clean my data

function sql_safe($value)
// Stripslashes
if (get_magic_quotes_gpc())
$value = stripslashes($value);

// Quote if not integer
if (!is_numeric($value) || $value[0] == ‘0′)
$value = mysql_real_escape_string($value);
return $value;

Just make all your user inputed data data like this

$var = sql_safe($_GET[“data”]);

This way, all invalid data is stripped out and your database is safe. This method is not an option, every application you make must have this or equivalent code, this is the only sure fire method that cant be hacked. If you do this with all your data, your site is safe from SQL injection attacks. The next two methods are icing on the cake, not hacker proof methods.

Method 2, Table prefixes
Fact of life is everyone makes mistakes, chances are pretty high you will forget to clean one user inputted data down the road, as small as the chance is, a cracker might find it. Most programs use standard names for their database, such as in a forum the table that holds the posts would be named “posts”. Crackers know this and will try every relevant name to the type of site it is. The best way to get around this is to add a prefix to your table name, instead of “posts”, make it “forum_posts”, even a common prefix like that makes it a good deal harder to hack. I use the first 3 letters of my control panel login name as my db prefix. Do not rely on this method, it just makes it harder for a cracker to get in should you miss a step.

Method 3, Don’t give sql user delete rights
This method is anything but a strict guideline, most of the scripts I make require deleting rows. But if it isn’t needed and you don’t have to delete rows, don’t give the user permission to. This will make it so that if you forgot to clean and he got the prefix, he can’t delete anything. Use it when you can, but don’t change a script to cater to this, it is little more then a final precaution.

Attack 2, forged data

What it is
Forged data is when you edit a cookie to make yourself look like an admin. The only way to let this happen is flawed design, generally static data or not confirming the data is question. As rare as it may seem, it is an error Ive seen allot, even in some scripts that are for sale. This one is more obscure, but it can happen if you encounter the wrong person. This can be worse then sql injection attacks because it is less apparent; you don’t have to destroy anything. Lastly, you normally have to have access to the script to do this, but not always.

How its done
Cookies can be edited easily, they are just text files on your computer. A cracker will go in and change the data to imitate what the script thinks is an admin. In firefox, to view the cookie all you have to do it go to tools -> options -> privacy -> view cookies. To change them you have to shut the browser off and go to C:\Documents and Settings\name\Application Data\Mozilla\Firefox\Profiles\profile name\cookies.txt

All your cookies reside in there, it is not encrypted so you can change anything you want to.

How to protect it

A lesson in how to make secure login cookies
What many scripts do is lay cookies like this
cookie 1:

cookie 2:

cookie 3:

This makes it easy to see if they are an admin or not, but there is one huge problem, all you have to do is change the rank cookie to what it looks for with an admin and you are in. This is a flawed design, what you have to do is this

cookie 1:
user ID

cookie 2:
user pass, encrypted via sha1 (you use sha1 when storing it in the db, right?)

When it sees a cookie, it will go into the database and see if the user with that id has that password. If it does, the user is who it says it is, you can see their rank in the database. If the data doesn’t match, you delete the cookie and they are off. The only way to hack this is to know the pass, and if the cracker knew that he wouldn’t be going in the back door.

Hold as little data as you can in the cookie, all it needs to do is provide solid data that the user in question is legit, not what rank they are.

I hope this article will help you make more secure PHP applications, if their is anything that has slipped my mind for this, please drop me a pm.


Feel free to post this anywhere as long as the below line is here
Originally written by Village Idiot of

No comments: