ASPit - Totally ASP JSit - Totally JavaScript
Search PHPit

Use this textbox to search for articles on PHPit. Seperate keywords with a space.

Advertisements

PHP Security: Basic PHP Security

(Page 1 out of 2)

Introduction

Security in PHP has become one of the most popular topics in the PHP community lately, especially with an increased number of exploits and security problems. In this day and age, you must make sure your PHP scripts are airtight, and that they don't have any security problems.

To make sure the security in your PHP scripts are okay, you have to start with the basics: filter input, and escape output. If you haven't got that working properly, your scripts will always be open to security problems. Read this article to learn how to properly do these two things.

Filter all input

When your script reads any input from an outside source, the input must be treated as dangerous and not to be trusted. The most common variables not to be trusted are: $_POST, $_GET, $_REQUEST but also $_SERVER, which seems unlikely but can also contain dangerous data.

Before you do any further processing with data that comes from a dangerous variable, you first have to validate it and possibly filter it. By validating the data you make sure that it contains only what you want it to contain. For example, if you're expecting an e-mail address, your validation function would make sure it's a valid e-mail address, and nothing else.

Let's have a quick example to show you what I mean. In the code below I first get the e-mail address from the $_POST variable, and then proceed to validate the data:


$email = $_POST['email']; # At this point it's still DANGEROUS

// Validate e-mail
if (valid_email($email) == false) {
        // Not a valid e-mail address
        die('Invalid E-mail Address!');
}
?>

The possibility to inject any dangerous data into our script has already been greatly diminished, by checking the data. The valid_email() function is a standard validation function, which can be found in the PHPit Code Snippet Database.

Even though our data is much safer already, we aren't completely there yet, because we still want to insert the data into a MySQL database, which means we must make sure it's safe to be inserted. PHP has a standard function called mysql_real_escape_string(), which escapes all the important characters. Another good practice is to always put data between apostrophes in the SQL query (if your database allows it, which MySQL does).

To continue our previous example, it now looks like this:


$email = $_POST['email']; # At this point it's still DANGEROUS

// Validate e-mail
if (valid_email($email) == false) {
        // Not a valid e-mail address
        die('Invalid E-mail Address!');
}

// Make sure e-mail is safe for database
$email = mysql_real_escape_string($email);

// All safe now!
?>

Now the data is completely safe, and can be inserted into the database without any worries. To help avoid mistakes it can be a smart thing to give special and dangerous variables a special prefix, for example:


$d_Email = $_POST['email']; # Dangerous

// Do validation

$s_Email = mysql_real_escape_string($d_Email);
?>

This way you will immediately notice when you're trying to insert a dangerous variable, because it'll show a d_ variable being inserted. I've never used this method myself, but once it you get used to it, it could be a lifesaver!

Next: Escape Output »



10 Responses to “PHP Security: Basic PHP Security”

  1. Matthijs Says:

    Good article Dennis. Filter ALL input, escape ALL output. Solid advice!

    One remark about prefixing variables to avoid mistakes. That is a good aproach. The method I personally apply is the one Chris Shiflett uses in his book. Start with declaring an empty $clean array. After that add only data to the $clean array after validation. Then, if you want to do something in your script, you only work with the $clean array. See for an example http://phpsecurity.org/code/ch01-3

    This makes sure you never process tainted/unsafe data, even if a variable hasn’t been declared earlier on in your script. For example, if I process some data like this:
    $clean = array();
    $email = $_POST[’email’];
    $sql = mysql_real_escape_string($clean[’Emali’]);
    as you can see, there’s a typo in the last line. But apart from the fact that my script probably doesn’t work as intended, it is not dangerous. The variable “Emali” can not be injected from outside, because I declare the $clean array empty at the start of the script.

    I find this approach very useful.

    On the other hand, if I would have processed the line as:
    $Email = $_POST[’email’];
    $sql = mysql_real_escape_string($Emali);
    the variable $Emali would not have been declared and could be injected from outside.

    Hope I explained it well. There’s a lot to consider when you want to write secure scripts, so it’s good you give it some attention Dennis! And the links you provide are indeed excellent reading material for further study.

  2. Volodia Says:

    $var[’email’]='’;
    $var=array_merge($var,$_GET,$_POST);
    $sql_query=”select * from table where email=’.addslashes($var[’email’]).’”;

    if in php.ini -> magic_quote_gpc=on
    $sql_query=”select * from table where email=’.addslashes(stripslashes($var[’email’])).’”;

  3. James Says:

    Hi, Sorry to be really picky, but i wouldn’t call this validation.

    [code]
    // Do validation

    $s_Email = mysql_real_escape_string($d_Email);

    [/code]

    Thats more what i would say is escaping, validation is checking the length and the characters contained within the username/email address. Stripping out HTML tags etc…I suppose you could call it data cleansing.
    Sorry to be a picky swine :)

  4. Charlie Says:

    > Start with declaring an empty $clean array. After that add only data to the $clean array after validation.

    Or better yes, use perl -T, and have the language *enforce* separation between validated and unvalidated data.

  5. Dennis Pallett Says:

    Matthijs: I really like the idea of the clean array, and it does prevent the mistake you describe, which is probably an all too common mistake, especially because a typo is easy to make.

    James: I kinda agree with you, although the valid_email() example I have is a good example of real validation.

  6. Piku’s PHP Blog » PHPit articles Says:

    […] First one is PHP Security: Basic PHP Security. It treats the basics of securing your PHP applications (Filtering the input and escaping the output). […]

  7. Brian Says:

    valid_email() is not available at http://phpit.net/code/

    It would have been nice to see.

  8. Dennis Pallett Says:

    Hi Brian,

    You’re right, and I’ve posted it now, at:

    http://phpit.net/code/valid-email/

    I’ve also updated the article. Thanks for letting me know.

  9. .:: ㊣Inosin℃ -> Blog ::. » 一个非常不错的Email地址验证函数~ Says:

    […] http://phpit.net/article/php-security-basic/1/ […]

  10. Marco Says:

    Italian resource / risorsa italiana sull’argomento: programmazione sicura in PHP:

    http://www.scuolaelettrica.it/buratto/php2/PHPSec.htm

Leave a Reply

About the author
Dennis Pallett is the main contributor to PHPit. He owns several websites, including ASPit and Chill2Music. He is currently still studying.
Article Index
  1. Filter Input
  2. Escape Output
Bookmark Article
Download Article
PDF
Download this article as a PDF file