Web Hosting Talk







View Full Version : Protect your code from XSS (PHP)


etogre
03-30-2008, 07:17 PM
Ahoy!

This effects everybody and should probably go into the tutorials section.

You may have heard of XSS (Cross-Site Scripting). The simple definition of this is when a hacker maliciously inserts javascript code into your page that then transfers information to their server.

The normal way of doing this is to use javascript to redirect the user to a page that captures their cookie. The hacker can then fake these cookies and login as your users (or even an admin account if they fall for the hack).

To understand XSS injection, you must understand that javascript is very adaptable, flexible, and can function even when it's source is completely changed.

For instance, say you have a PHP program that allows users to insert BBCode into their messages which are then displayed.

Perhaps the source for your [ img ] tags produces the following:

<img src="$url" alt="" />

Now say random hacker A comes to your site and decides to test some of his leet hackiness on your page and tries the following:

[ img ]javascript:alert('XSS');[ /img ]


Now you're no dummy, so you run all user input through the htmlentities($str, ENT_QUOTES) (http://www.php.net/manual/en/function.htmlentities.php) built in PHP function before displaying it to your users, and thus on the page source the code is displayed as such:

<img src="javascript:alert(& #039;XSS& #039;)" alt="" />

But remember what I said about javascript being very flexible and able to work regardless of the problem? Copy and paste that last code block into a HTML file and run it in IE 6.0 and you'll get an alert window. This could instead be a URL redirect that captures the users cookie, XSS.

So, how do we handle this?

Simple, we just have to change the way we display the data by adding another function that will help us:

function js_sc($str)
{
$pattern = '/javascript:/';
$replacement = '& #74;& #97;& #118;& #97;script& #58;';
$string = preg_replace($pattern,$replacement,$str);
return $string;
}

This example is case insensitive.

So you can see we have converted the first four letters (Java) into their HTML entity values, as well as the colon ( : ).

BUT WAIT!

What did I tell you about javascript being very flexible!!

That's right, even by doing that much garbling of the javascript source, it can still function as the hacker intends!!


"So you said there was a simple solution, and you're boring me with the javascript lesson!"

Well, the simple solution that is used by phpBB, vBulletin, etc. is to simply split the source up with HTML tags.

for instance, we want to do this:

javascr<b></b>ript:alert('XSS');

This will stop XSS injection in its tracks, while still allow messages to say the word javascript in them without changing the way it looks in the browser.

This is easily accomplished through our simple (and final!) function:

The real deal:

function js_sc($str)
{
$pattern[0] = '/script/';
$pattern[1] = '/on/';
$replacement[0] = 'scr<b></b>ipt';
$replacement[1] = 'o<b></b>n';
$string = preg_replace($pattern,$replacement,$str);
return $string;
}

In this final function, we tell it to find any instance of the word "script" in any context, this is because besides javascript their is VBscript and whatnot. This will eliminate all scripting. We added "on" to the mix, since some XSS attacks involve manipulation of "onerror, onmouseover", etc. Again, this will not effect legitimate output in anyway.

Putting it all together, this function in use:


$str_from_db = "javascript:alert('XSS')";
$str = htmlentities($str_from_db, ENT_QUOTES);
$str = bbcodeparse($str); // this function is not explained in this example, this would be a user-made function that you make if you wanted to add bbcodes
$str = js_sc($str);

echo $str;




For more reading on XSS, here's the wikipedia link: http://en.wikipedia.org/wiki/Cross-site_scripting

Because XSS is such a pain, even this example might not solve every vulnerability, but it is a start. Please discuss other methods here if you know of any.

Happy coding!

(PS I had to add spaces in some of the examples because vbulletin comprehended it as-was)

larwilliams
03-30-2008, 11:53 PM
Another good idea is to use mod_security for Apache, as it can help defend against the more common attacks like SQL and URL injections.

1boss1
04-04-2008, 07:39 AM
Good article. Another good practice is to only allow the expected content with any user input. For instance if you are expecting an email or image URL to be input do not allow parsing of anything else, or if your CAPTCHA is 5 characters in length dont except anything greater or less than 5 characters.

This alone isnt perfect in every case, but it helps to keep everything tight when laying the foundations.

BlueHayes
04-04-2008, 08:23 AM
Great! Should perhaps be in one of the tutorial forums :stickout: Thanks very much :)

Codebird
04-05-2008, 06:36 PM
you said there was a simple solution, and you're boring me with the javascript lesson! :D Thanks needed it so much right now!!!

orangewebhosting0net
04-06-2008, 05:51 PM
Surly the simlpest solution would be to re-write all urls with seo friendly ones so the hacker couldnt get acess to live urls all the ones displayed are created on the fly and static so they cant do anything with them? any views on this?

BlueHayes
04-06-2008, 07:05 PM
Surly the simlpest solution would be to re-write all urls with seo friendly ones so the hacker couldnt get acess to live urls all the ones displayed are created on the fly and static so they cant do anything with them? any views on this?

What do you mean by this? How would this protect from the likes of inserting bad Javascript into your application using BBCode?

larwilliams
04-06-2008, 07:25 PM
Your best bet is using mod_security and good rulesets.

foobic
04-06-2008, 09:34 PM
Your best bet is using mod_security and good rulesets.I disagree. Mod_sec is a useful precaution but no matter how good the ruleset it cannot fully protect an insecure application. The first priority should always be to design the application to be secure.

Personally I'd rather block untrusted users from entering HTML / BBcode at all, but where it is necessary (forums etc) the OP's approach seems solid.

BlueHayes
04-10-2008, 09:41 PM
What happens if you have BB code such as [img] and somebody enteres [img ]http://some/url/on/here.png[ /img] - the function will then match "on" and put html tags in it... meaning the users image won't show up?

Thanks

VentureMaker
04-11-2008, 09:13 AM
I have disabled fopen() of my servers :) That solved many problems

OmadaSite
04-11-2008, 12:02 PM
All good, but all you have to do is validate the data in a preg_match for instance in php. As a good programmer, you should always validate that the client input is what is expected and filter any unexpected data out. If you are expecting a url, then a simple 1 line of regex will validate the data is valid.

Good info though in explaining the problem to newbies though because it further demonstrates to them why they have to process the incoming data as if it has been injected with something harmful.

I never trust anything from the http client and never pass it without filtering it for garbage data. As long as a programmer lives by the rules of not trusting any data from outside sources, you should be fine.