10 common PHP security mistakes

23 August 2011

Security is an often overlooked part of PHP programming. So therefore, I present you the basics of PHP security: the ten most common PHP security mistakes.

1. Never include files from user input



Creating a navigation seems easy when you do this:

<a href="index.php?page=welcome">welcome</a>

And then include the page like this:

include($_GET['page'].'.php');

This is really dangerous. Hackers can use this to display/include/run every file on your server, and even on other servers!

2. Register_globals = ON



This option was introduced a long time ago to make development in PHP easier, but it added a lot more problems security-wise. What it does: it registers variables from (for example) the query string (?page=filename) as global variables. This way hackers can overrule variables by setting them in the address bar of the browser. Luckily this feature is depricated from PHP version 5.3.0 on.

3. Always validate data used in eval()



There are very few situations where eval() is neccessary, but if you can't avoid using it, always validate the string that is executed by eval(). Especially when user generated content is parsed by the eval() function.

4. Never execute unescaped queries



To prevent MySQL injection, always escape all variables in any query. For example: if somebody enters this as his or her name in a contact form:

johan'; DELETE FROM customers WHERE 1 OR username = '

The insert query will look like this when you don't escape the user input:

INSERT INTO contact SET name='johan'; DELETE FROM customers WHERE 1 OR username = ''

Wich inserts a record (like it is supposed to do), but also delete all records from the customers table. To prevent this, use the mysql_escape_string() function (or something similar) to escape user input.

$q = "INSERT INTO contact SET name='". mysql_escape_string($name) ."'";


5. Check the $_SESSION in every protected page



If you have a protected area in your site, like a CMS, commenting system, forum, etc. you probably use sessions to store logedin users. Check the session on EVERY page that is protected. Easiest way to do this is to include a file in the first line of every page, that checks the session for a user to have the proper right to view the page.

6. Always use .php as an extension



Use a .php extension for all files used in a site. The webserver parses all files with a php extension and will never display the contents of the file. If you name a file with .inc, .ini, or .conf the server will not execute the file when called directly, but just display the contents of the file. Especially dangerous with config files containing database logins...

7. Input validation



Alsways validate all user input. If an entered value should always be an integer, always check the value with intval(). If a user can enter text (to leave a comment on a blogpost, for example) always strip all HTML tags with strip_tags(), etc. There are many functions in the PHP library to validate and strip user input.

8. Output filtering



When displaying user generated content, like comments on a blogpost, always strip and escape there content. htmlspecialchars() converts all special characters to there html entities thus preventing HTML code to be rendered by the browser. Strip_tags() goes a step further and strips out all HTML tags, including JS, CSS, etc.

9. Don't display errors



Turn of error reporting. Many errors generated and displayed by the server contain information that is usefull for hackers to hack your site. Tablenames, file locations, etc can be used in MySQL injections and other hacks. You should hide all error and warning reports and mail them to yourself (only if your confident with your coding skills or if you don't mind deleting a lot of mails every day) or only display reports for certain IP's (at your home or something).

10. Redirect after form actions



One of the easiest ways for somebody to do harm to your site is to keep pressing F5+ENTER after submitting a form and keep repeating the action. You wouldn't like to log in to your database each morning to delete another 5000 comments that some scriptkiddy entered in your blog. To prevent this, redirect somewhere with the header('location: ') function. Easiest is to redirect to the same page, or back to the previous page and display a succes message.
You must have JavaScript enabled to use this form!

Leave a comment!

  1. Your mail is safe with me. It's only only used to display your Gravatar image!

4 comments

  1. Gravatar

    Chris Cornutt

    04 June 2014

    One thing here, it's usually advised to use bind variables and prepared statements (PDO in PHP's case) over trying to escape something with the MySQL escaping function(s): http://php.net/pdo.

    SQL statements should *never* be the result of concatenated strings.

  2. Gravatar

    Farag Elfadaly

    05 June 2013

    very good article, show the idea obviously....

  3. Gravatar

    Philinda

    03 September 2011

    Tip top stuff. I'll epxcet more now.

  4. Gravatar

    Alex

    24 August 2011

    Storing all back-end (e.g. everything below the UI layer) outside the webroot is also a good thing. It makes them inaccesible via HTTP, even in the case of configuration errors. Also, redirect errors to a logfile instead of displaying them to a visitor. It's a little security-by-obscurity, but error messages can give away a great deal of information like SQL usernames, (parts of) queries, etc.