Do you remember the last website which was hacked by some kids? What was your first thought, maybe “Phew, that’s not mine”? A hacked website is terrible and the clean-up is a lot of work for the site owner. As a website owner you need to be sure that your site is always secure. It’s important for your business and of course for your site listing in Google. Remember these tips when creating secure PHP websites:

MySQL queries and SQL injection attacks

If your web page accepts user input a SQL injection might happen if the data isn’t validated or sanitized before the database query is done. The following example is a common mistake, made by the beginning programmer or webmaster. Check this code, do you ever wrote a MySQL query like this one?

This row of code is written to accept two values from a login form: a user name and a password. But what if someone will submit an empty user name and for the password value the following string:  ‘ OR username = ‘admin the query would look like:

Creating secure php websitesIf this query was used for a login script, the hacker would get access to the account for the user with the name “admin”. Imagine what a hacker could do in your web application if he has administrator rights. Don’t worry there are several ways to protect your queries against SQL injections.

First of all it’s better to use the MySQL improved extension (MySQLi). The old PHP functions for MySQL are still available, but the MySQLi extension offers more secure features. If you use the MySQLi functions you can choose between procedural style and the object oriented style. I use for my examples the object oriented style.

Before I escape the values for our queries we use the function filter_var() to sanitize the input values.

My example is using the default value for the filter type FILTER_SANITIZE_STRING. Next I use the MySQLi variant of mysql_real_escape_string() to prepare the strings for the database query. Before I can continue with the input validation, I need to create a database object first. Don’t store passwords as plain text! To match the value in your database we need to use the same md5 / salt (secret string) to create the comparison string inside the query.

Now it’s safe to pass these values to our database query:

In my example I used the function sprintf() to add the values to the query and use the $db->close() to destroy the database object. Another great and secure MySQLi feature the prepared statements function.

Cross Site Request Forgery (CSRF) Attacks

The basic principal behind a CSRF attack is not to get access to a site, but forcing a user or admin to an unwanted action. For example we have an admin page with a HTML structure like this one.

We have protected the page named delete.php with some login script, that a user without permissions can’t access the page or script.

The script dies if the user isn’t logged in and otherwise the page with the page ID from the GET variable will be deleted. By using the function sprintf() I’m able to format the value to an integer value by using the type specifier %d. Seems to be safe or not?

Let’s say the authorized (logged in) would visit a page where a comment was posted including an image. If a hacker has posted an image with the URL like the one below you wouldn’t notice it, because the image doesn’t show up because the URL doesn’t exists.

Sure this is a very stupid example and the hack is only possible if the hacker knows your PHP website security. A much better solution would be to use a unique token for each important action. The best way is to create a unique token for the admin user during login. Let’s say the code below is a part from your login script. Inside the login_user() function I create a session variable than contains a md5() encrypted string.

Inside the page with the HTML structure I need to add the token variables after each link.

With this additional token variable inside the delete.php script I’m able to validate the data input.

This simple validation will stop the script if the token is missing or not equal to the token session variable.

Cross site scripting (XSS) Attacks

The basic idea of XSS attack is that a hacker has embedded some client-side code on your web site which is executed or download by a visitor. This happens in different ways. For example by using a link to your website where some malicious JavaScript is added or the hacker has posted some JavaScript code to your website. The last one happens mostly by using unsafe comment forms where the content find a place on your website.

In any situation it’s important that your web application sanitizes the user’s input before the data is stored or parsed in your web page. Use different validation functions like preg_match(), filter_var() or better htmlspecialchars() to filter or convert possible attacks from hackers. The function htmlspecialchars() will convert HTML tags into entities.

Limit script functionality

If your website has a login function, it’s possible that a hacker will use a script that will try guess a user name and password. While using thousands of combinations it’s possible that the hacker will succeed. Throttle down the access to your login page if a visitor has made more than X submissions and use always passwords which are hard to guess. Common passwords like “welcome” or “default” are most of the time the cause of getting hacked.

Be careful with the function to recover a password. Never send the recovery instructions to some new email address and let the owner of the registered email address execute the recovery action.

Captcha images are a great and simple way to stop bots accessing your web forms. Use them where a remote submission can harm your web application.

Disable PHP error reporting

There are many reasons why some PHP error can happen on a website. Many of them doesn’t have any influence on the web site’s functionality. For a hacker is a notice or error message a source to get information about your website and/or sever configuration. Test your website always for possible error, because they are bad for your website and/or business, too. Would you trust a service that is broken?
There is also a functions that disables the output of error messages, add ini_set(‘display_errors’, 0); to your script and show errors ONLY on your test location!

I hope this tutorial helps to understand some basic concepts how a hacker will try to attack your websites.

Disclaimer: This article is written to explain common problems I have seen very often. Don’t use the examples in production!

Don’t make these mistakes when creating secure PHP websites!

Pin It on Pinterest

Share This

Share this post with your friends!