Wednesday, February 17, 2010

PHP Protection from XSS attacks

If you have a forum, or blog hosted on your site. Then you should be aware of cross site scripting vulnerabilities that any basic HTML form can produce. I will show you how the vulnerability exists, how to detect it, and how to mitigate this form of attack.


What is an Cross-Site Scripting (XSS) Attack?

Cross site scripting vulnerabilities are produced when a web site displays unfiltered user generated input on to the site. By allowing users to supply their own content, hackers can figure out ways to get malicious content on the website by injecting it with their own scripts via javascript and change the behavior of your site. This can include redirects to untrusted site, stolen cookie/session, loading exploits to vulnerable browsers/operating systems, execution of viruses/trojans on a users machine etc...

The vulnerability is only escalated as this input is then placed on a database. Depending on your traffic and the popularity of your site (mind you the social engineering the hacker has done to make this posting with malicious content appealing to the public eye) all of your users that view the hackers page have been compromised and in many cases don't even know it.

How do you tell if your site is vulnerable?

Fortunately, telling whether your site is vulnerable is pretty simple and straight forward. From the front end, its as simple as putting up an alert box in your post and seeing if the alert box is generated when you view your content. From the the Business Logic (server-side), look for possible neglected areas where you are taking users input from a database and re-displaying it without any restraint.


Protecting Against XSS Attacks

Although the vulnerability is a big deal, protection is not as painful as the attack. You must always remember to properly validate your data fields in your server-side coding. I cant stress that enough. Client-side validation can be easily defeated. Best practice: you can have client-side validation and strictly enforce it on the server-side. This way if one fails, its the server to the rescue lol.

There are several functions within PHP that allow you to mitigate this hole. First of which is htmlentities(). It basically returns any HTML characters and returns its entity form. You just pass in the string that you want to filter. htmlspecialchars() function works the same as the first function. One might also use strip_tags() to only allow tags that you specify and strip the rest of the tags from the input. You might also want to use preg_replace() function if you have a specific pattern for the data to be molded into. Validation is a good practice to mitigate a number of security holes.


Examples


Here's an example of an insecure string that is displayed on the page:


<?php
$srt = "hello this is a example of a normal user generated input";
echo ("User Generated Output: $str");

/******************
GENERATED OUTPUT:
*******************/
/*
User Generated Output: hello this is a example of a normal user generated input
*/
?>


Here I am taking input from a user and displaying it on the page. This input could be from a $_GET[] or $_POST[] associative arrays. What's the problem with this?

Well, if a user were to enter something like this:


$str="<script>alert(\"hello this is a test xss attack simulation!\");</script>";


Output would be of an alert box similar to this one(shown below). Which tells a hacker that they can execute the code with no problem to do there dirty work.

1. A way to secure this would be to incorporate one of the functions discussed above. This example uses htmlentities() function.


$str="<script>alert(\"hello this is a test xss attack simulation!\");</script>";
echo ("User Generated Output:". htmlentities($str);

/******************
GENERATED OUTPUT:
*******************/
/*
User Generated Output: <script> alert("hello this is a test xss attack simulation!"); </script>
*/

Instead of executing the line of code it displays it as a string of text, keeping it from executing in its literal form.

2. If your really paranoid about this, you would use a pattern to match the specific form of data that you expecting to get. In this example I am expecting alphabetic input nothing more nothing less. Lets take a look:


$r=preg_replace("/[^a-z ][\d\W]*/i","",$str);

echo("User Generated Output:".htmlentities($r));

/******************
GENERATED OUTPUT:
*******************/
/*
User Generated Output: scriptalerthello this is a test xss attack simulationscript
*/

This example not only blocks all <> characters (used to open/close a tag) it also blocks any special chars as well. It replaces the found chars with blank char so its concatenated with the remaining string. This is a little unnecessary (overkill) but it works.

Conclusion

Remember to always check your data through validation before you display the context of users input. I have showed you some functions that I'm sure will help you in your quest to secure your applications.

No comments:

Post a Comment

Please leave me a few lines and tell me what you think.