Blog Posts

Missed case in externalinput.php resulting in viable XSS attacks - fix available

About 3 weeks ago I got contacted by Will Drewry from the oCERT Team about a possible XSS attack vector in the popoon externalinput class, which was discovered by Alexios Fakos. It used a (again stupid) behaviour by browsers which treat a "/" like a space, so something like <body/onload=alert(/hello/)> was not cleaned up... The actual fix was quite easy and a no-brainer. But as I always said that externalinput.php alone should not be used as your own line of defense, I went for a more thorough solution.

Many issues with cleaning XSS attacks comes from the fact, that browsers accept a lot of really f***ed up markup like the example above and therefore before actually trying to clean unwanted stuff away one should make a well formed HTML out of the input. Tidy does that job pretty well, the loadHTML method of PHP's DomDocument class also produces well-formed XHTML as output. That's what I always told people to do and that's what we do since always in Flux CMS. That's why Flux CMS is not affected by this exploit at all - some of the advantages of XML based CMS systems.

To more enforce that approach, I wrote a new class called lx_externalinput_clean, which uses the same regexes but does by default filter first the input with tidy, and if that's not available with DomDocument->loadHTML and if even that is not available, it does a striptags(), just to be sure. This can be overridden, so that if you do that cleaning already before, you don't have to do that again. I hope this helps people just blindly copying code :)

Having said that, the class still tries to clean many nasty things without first having to tidy up the HTML to get proper markup (and the above attack is also handled without tidy et al.). But there are most certainly more attacks possible which come from WTF-a-browser-does-parse-that? markup and using those tools should get rid of them for once and all. You have been warned, if you don't use them.

You can also test the "new" tool over at labs.liip.ch/xsscleaner and check, if you find more vulnerabilities.

Thanks a lot to the oCERT team to give me this much time ahead to fix it and to inform a lot of other projects in advance which are apparently using my code.

The full advisory can be found at http://www.ocert.org/advisories/ocert-2008-012.html

Related Entries:
- More XSS Update
- XSS Roundup
- XSS - How we try to prevent it.
- The first blogcamp Switzerland

About the author

Comments [13]

Yoan, 10.09.2008 19:38 CEST

This case remains:

<span style="font-weight:expression(alert(/XSS/))">moo</span>

Yoan, 10.09.2008 19:41 CEST

Grrr, the comment preview isn't like the final one... here we go:

<span style="font-weight:ex\pression(alert(/XSS/))">moo

Chregu, 10.09.2008 20:59 CEST

You're right, that's indeed exploitable with IE, if you don't use tidy before.

As it gets too annoying and one in general doesn't want people using style attributes anyway, the latest version now just strips away style tags, problem (hopefully) solved.

Tomek, 10.09.2008 22:17 CEST

what about HTML Purifier?

Chregu, 10.09.2008 22:43 CEST

There's nothing wrong with HTML Purifier IMHO :)

x, 13.09.2008 08:06 CEST



if the blog filters mangle it... the idea here is that a few of your regular expression filters get confused when there's a close tag located within an attribute's value, allowing style expressions or on* event handlers to evade filtering.

Chregu, 15.09.2008 10:46 CEST

x: can you send me via e-mail, what you think is still an attack vector

Sven, 19.07.2009 16:00 CEST

This:

$doc = new DOMDocument();
$doc->loadHTML("<span style="width: expression(alert('Ping!'));"></span>");
echo $doc->saveHTML();

still are not cleaned...

Chregu, 19.07.2009 16:23 CEST

Sven? the dom extenion itself doesn't do XSS protection, noone did claim that.

Sven, 19.07.2009 22:53 CEST

Ok, I am pretty new to using php classes, could you give me an example on how to use your script in php?

Thanks :-)

Chregu, 20.07.2009 14:46 CEST

Sven:
***
include_once("lx/externalinput/clean.php");
$cleandhtml = lx_externalinput_clean::basic($html);
***

The clean.php you get from https://svn.liip.ch/repos/public/ext/externalinput/trunk/lx/externalinput/clean.php

Sven, 21.07.2009 10:55 CEST

Thanks Chregu :)

huazai, 14.07.2011 03:36 CEST

有中文教程嘛?
do you have chinese course of XSS?
all is english it's hard to study!.....

Add a comment

Your email adress will never be published. Comment spam will be deleted!