Web development security tips (PHP)

I’ve seen a lot of hacked websites lately (most because of SQL Injection). Almost all the security problems occur because us web developers assume that the users will act naturally and because we’re lazy to keep testing all the input data or wonder what if?. This is not a how to hack article, but it should give you, the web developer, some basic ideas to develop a more secure website.

First line of defense

Cross-site scripting (XSS)

Do you have an input somewhere on your website? Have you tested what happens when you type in html tags? What about HTML tags with JavaScript actions?

My best solution is a classic htmlspecialchars() on the whole user input when displaying it on a web page. Of course, If you want some extra styles for the text you can always use BBCode.

Be careful when trying to manually strip HTML tags form strings. You may find out that many browsers tend to correct bad formatted tags and interpret them. Here’s an example that will be interpreted even though it’s not XML compliant:

<script src='http://www.badguy.com/badscript.js' </script

SQL Injection

On a database driven website, you will almost certainly save data provided by your users in the database. This means that you will perform a query using unknown strings. Let’s have a look over a simple example. The user typed in the following string in a comment:

I don't like this article.

On the next page, you have the following code:

mysql_query("INSERT INTO comments(`content`) VALUES('".$_POST['comment']."')");

The SQL server will be left to execute the next query.

INSERT INTO comments(`content`) VALUES('I don't like this article.')

This will obviously result in a SQL error because of the apostrophe from don’t. This isn’t such a big deal but then again, the user didn’t mean to do any harm. You may argue that PHP has the magic quote but they’re not so effective.

A more frequent SQL injection method is through the GET parameters. Yes, you must make sure that$_ GET['id'] which will be used in “SELECT * FROM `articles` WHERE id=’”.$_GET['id'].”‘” is numeric.

Don’t assume anything

Just because there is no outside link to some specific administration page doesn’t mean that you shouldn’t test the user’s credentials.

Watch for scripts called with AJAX. Each one is called using a different HTTP request so you need to test the user in each of those.

Second line of defense

It seems that some people were stubborn and ended up with a little more access to your website than they should have. What can you do now to minimize their mess?

Encript user passwords

I don’t know why some  still keep their all the users’ passwords in plain text. This is also a matter of privacy. You wouldn’t want the webmaster to know everybody’s password, would you?

Assign read-only privileges to the database user

Most web applications will only use basic CRUD functions. So why give the possibility to ALTER TABLE, DROP DATABASE, etc?

Setup an automated database backup script

Make sure the database is backed up regularly. In most cases it is more important than the script files which normally have an off site backup on your HDD.

Here’s a shell command which can easily be inserted into a cron job (should be set to run daily):

date=`date -I` ; mysqldump -h localhost -u db_user -ppassword database_name | gzip > /home/your_user/mysql_backup/backup_$date.gz

And make sure that the folder where you store your backup isn’t public!

These are the only the first things that came in mind right now. I don’t want to turn this article into a book so I will end now.

I you have something to add just post a comment.

Leave a Reply