Tuesday, July 17, 2007

Chasing Vulnerabilities for Fun and Profit III

I’ve written before about WhiteHat Security office events in which we race to find the first and best vulnerability in never-seen-before websites - the winner receiving company-wide bragging rights. Speed hack contests are also great for learning and testing one’s skills. They get the competitive juices flowing, typically finish in less than 20 minutes, and keep the day-to-day work fun! Lately, winning has proved to be extremely challenging, especially when you’re up against people like Bill Pennington, Arian Evans, and the entire Operations Team who does this stuff everyday.

We ran two bouts last week. The first was a financial application, which was a little bit different, because it had a social networking aspect. We weren’t provided any usernames or passwords, couldn’t self-register without a special code; and, as a result, the attack surface was limited. This meant we could still probably find the first XSS fast, but the high-severity issue probably wasn’t going to be there. The domain was called out, fingers hit the keyboard, and we were off. Bill P. and I went immediately after XSS in the search fields, but struck out because of proper HTML encoding. Arian, who only sees filters as a challenge, busied himself with some crazy encoding attacks. The rest of the Operations Team were eagerly trying to take down the giants.

One, two minutes flew by with every avenue of attack closed off. Input sanity checked, output encoded, use of custom error messages, and directory indexing disabled. Not one to be easily frustrated, I was getting nervous because only 3 minutes in, application real estate was running out. Then just like that, at ~3 minutes 30 seconds, Daniel Herrera (security engineer) scored an XSS victory with a simple form-based injection in the user registration form. Something I had totally overlooked. Not wanting to be shut out completely, BillP and I found our own form-based XSS issues after 4 and 6 minutes time respectively. Too little, too late. No high severity issue was found after exhausting our options without valid accounts.

The second contest was a little bit different. This was not a customer website, but an Arian Evans’s special originally designed to test the capabilities of Web application vulnerability scanners. Arian pointed to the exact location of a parameter that was vulnerable to XSS. But, it was guarded by a complex blacklist that had to be bypassed in order to get a working exploit. This was our challenge. No accounts were necessary, so I figured this should be a fairly quick and easy exercise. To sweeten the deal, I put lunch on the line for the first person to bypass the filter and issue a JavaScript alert.

The green flag dropped and Arian assumed the role of referee/comic relief, (which he plays very well). I hammed on the filter, noticed the blacklists denying keywords like “alert“, “javascript”, “document”, “window” and only allowed a set of limited “safe” HTML. I managed to get JavaScript to execute via an <* input src="http://aaaa/" onerror="a" type="image"> quick enough. But, because of the blacklist, I couldn’t pop a window FTW. 2 minutes turned into 5, which turn into 10, then 15. Argh! I couldn’t get the filter to break. Meanwhile, Arian is teasing me for being so close but yet so far.

~15 minutes, Sarah Groark (Sr. Security Engineer), scored a very clever filter-bypass win using hex HTML entities:
<* BODY ONLOAD=&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;&#x3B;>
Decoded: <* body onload="javascript:alert('XSS');">

I had tried decimal HTML entities earlier to beat the filter, but gave up on it because the filter was immediately wise to it. Adding insult to injury, Sarah took a few minutes break to get some water and a yogurt. Shortly afterwards, I was overheard saying, “I got beat by a girl!?”. To which Sarah replied, “That’s because girls rule!”, and under the circumstances I was in no position to debate the point.

I did manage to complete my hack without using any encoding at all 3 minutes later:

<* input%20type=image%20src=http://aaaa/%20onerror=x%3d'aler'%3bx%2b%3d't(\'arian_i5_0wn3d!!1\')'%3beval(x)%3b>

Decoded: <* input type="image" src="http://aaaa/" onerror="x="'aler';x+="'t(\'Arian_i5_0wN3d!!1\')';eval(x);">

Clever? Sure. But, not fast enough.

You win some, you lose some I guess. Maybe all this press and presentation stuff is ruining my skills! ;) Hopefully, InfoWorld won’t take away my CTO award!

14 comments:

Arian Evans said...

Okay -- Let's be clear: I almost got encoded HTTP Response Splitting working on the discussion forums, but they linked in code from a 3rd-party host so I had to stop :)

Went for the gold....wound up last. /sigh

The XSS examples in my app are all taken from discoveries made in REAL WORLD products -- many you know and use. So they aren't contrived "trick the scanner" tests. They are reality. Many types of XSS in this app that we know only WHS Sentinel can find (compared to the other scanners -- see Hacking Exposed Web Apps for more).

Several engineers got really close. Kevin Phan and Mitch Poortinga both pretty much had it at one point, but then went down a side path. Daniel Herrera and Ryan O'Leary were also within inches, but got into double and triple-encoding and made it TOO difficult. (we do find *crazy* double-triple encoded stuffs in production software, usually only in really large, complex apps).

But the bottom line is that we all know Sarah is wicked-smart, and now everyone knows Sarah is smarter than we are. It took me *hours* if not *days* to find the key to that blacklist bypass when I first ran into it. :)

And it only took jeremiah *minutes* to find a new way I'd never have gotten working....

Sarah Kenna Groark said...

You should try taking yogurt breaks during speed hacking contests, Jer. Yogurt: the hacker's secret weapon.

Jeremiah Grossman said...

Popeye: Spinach
Scooby: Scooby Snacks
Hackers: Yogurt?

Hmmm. :)

david said...

Does Sarah have a blog? Maybe I should be reading hers instead of this one.

bob said...

Pwned like a noob jeremiah!

kl said...

top['al'+'ert']('xss')

Anonymous said...

Speaking of filter bypassing, has anyone been successful in getting past Microsoft's System.Web.HttpRequest.ValidateString filters?

Arian Evans said...

Depends on what version of .NET you are referring to. I've got some unpublished bypasses for 1.1 and a few for 2.0, that I believe are all silently fixed in 3.0.

Some of them are more like "filter not properly being invoked on all parts of the HttpRequest it should be" than a "bypass ValidateString" . But anyway...they work.

-ae

Anonymous said...

Was "beat by a girl" causing problems at the office? :)

Jeremiah Grossman said...

Yes and no. No with the girl in question, but yes as others might view it as sexist. Either way in California, one must be extremely PC.

chriscla said...

Can you elaborate on Sarah's bypass? I am not sure if I see what she did. Did she encode all of the characters using an ampersand-X-number-colon? If so, why would the page un-HTML encode them before placing them in the body?

Sounds really interesting, I would just like a little more detail.

Jeremiah Grossman said...

Hi chriscla, something screwed up in the encoding of the post, but I think I fixed it. Here is is again just in case.


<* BODY ONLOAD=&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;&#x3B;>

chriscla said...

Thank you for fixing the encoding, that makes a lot more sense.

This works because you are able to supply unencoded open tag brackets into the output. If the open tag brackets had been encoded then there wouldn't be the possibility to inject the script using this method. Another thing to do would be blacklist all strings that start with ON so as to remove the ability to provide event handler attributes.

Anyway, it makes a lot more sense to me now that I see the encoding as it was submitted in the attack.

Jeremiah Grossman said...

Yah its a really nice trick. Anytime you allow HTML, its a slippery slope... and from my point of view... destined to fail.