Thursday, April 23, 2009

Blacklisting and XSS Failures

Looking at a financial application, I was somewhat surprised to see blacklisting of angle brackets used as the main countermeasure against cross-site scripting. Stripping angle brackets or throwing an error every time you see one in a request is not sufficient protection against XSS. There were a couple of ways to exploit XSS in this application despite the rigorous rejection of angle brackets.

One attack vector was due to a page that accepted a parameter containing a relative URL to another page in the application. It ended up being a tailor-made way for someone to avoid the blacklisting altogether. When a request was received, this special page caused a forward (not a redirect) to the specified URL. The code that rejected angle brackets was hit on the request from the client only, and not when the forwarding was done. Therefore, "<" and ">" could be slipped in by double URL-encoding them in the initial request as follows: %253C and %253E (%25 is a URL-encoded percent sign).

The other XSS attack vector was via JavaScript event handlers. This technique is available when user-supplied data is output to the attribute list of a page element. This often happens for an <input> tag, where the HTML form has multiple text inputs. The user enters the data, but one or two values may be invalid, so the application returns the same page and prepopulates the values that were entered. An attacker can employ XSS by closing off the previous attribute with a double-quote (assuming double-quotes were used) and injecting an event handler such as onMouseOver, onFocus, or onClick.

An example injection is: x%22%20onFocus%3d%22alert('xss')%22%20%22. The resulting HTML might look like this:

<input type="text" name="val5" value="x" onFocus="alert('xss')" "">

Notice there were no angle brackets used in this attack, so blacklisting those characters did not provide any protection.