We´ve all known that the main problem of constructing XSS attacks is how to obfuscate malicious code. In the following paragraphs Cheng will attempt to explain the concept of bypassing script filters with variable-width encodings, and disclose the applications of this concept to Hotmail and Yahoo! Mail web-based mail services.
A variable-width encoding(a.k.a variable-length encoding) is a type of character encoding scheme in which codes of differing lengths are used to encode a character set. Most common variable-width encodings are multibyte encodings, which use varying numbers of bytes to encode different characters.
The first use of multibyte encodings was for the encoding of Chinese, Japanese and Korean, which have large character sets well in excess of 256 characters. The Unicode standard has two variable-width encodings: UTF-8 and UTF-16. The most commonly-used codes are two-byte codes. The EUC-CN form of GB2312, plus EUC-JP and EUC-KR, are examples of such two-byte EUC codes. And there are also some three-byte and four-byte codes.
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body>
echo "Char $i is <font face="xyz".chr($i)."">not </font>"
."<font face=" onmouseover=alert($i) notexist=".chr($i)."" >"
// NOTE: 5 space characters following the last "
For most values of $i, Internet Explorer 6.0(SP2) will display “Char XXX is not available”. When $i is between 192(0xC0) and 255(0xFF), you can see “Char XXX is available”. Let´s take $i=0xC0 for example, consider the following code:
Char 192 is <font face=”xyz[0xC0]”>not </font><font face=” onmouseover=alert(192) s=[0xC0]” >available</font>
0xC0 is one of the 32 first bytes of 2-byte sequences (0xC0-0xDF) in UTF-8. So when IE parses the above code, it will consider 0xC0 and the following quote as a sequence, and therefore these two pairs of FONT elements will become one with “xyz[0xC0]”>not </font><font face=” as the value of FACE parameter. The second 0xC0 will start another 2-byte sequence as a value of NOTEXIST parameter which is not quoted. Due to a space character following by the quote, 0xE0-0xEF which are first bytes of 3-byte sequences, together with the following quote and one space character will be considered as the value of NOTEXIST parameter. And each of the first bytes of 4-byte sequences(0xF0-0xF7), 5-byte sequences(0xF8-0xFB), 6-byte sequences(0xFC-0xFD), together with the following quote and space characters will be considered as one sequence.
Cheng doesn´t think there is a typical exploitation of bypassing script filters with variable-width encodings, because the exploitation is very flexible. But you just need to remember that if the webapp use variable-width encodings, you can bury some characters following by your entry, and the buried characters might be very crucial.
The above code might be exploited in general webapps which allow you to add formatting to your entry in the same way as HTML does. For example, in some forums, [font=Courier New]message[/font] in your message will be transformed into <font face=”Courier New”>message</font>. Supposing it use UTF-8, we can attack by sending
[font=xyz[0xC0]]buried[/font][font=abc onmouseover=alert() s=[0xC0]]exploited[/font]
And it will be tranformed into
<font face=”xyz[0xC0]”>buried</font><font face=”abc onmouseover=alert() s=[0xC0]”>exploited</font>
Using this method, Cheng has found two XSS vulnerabilities in Hotmail and Yahoo! Mail web-based mail services. Cheng has informed Yahoo and Microsoft on April 30 and May 12 respectively. And they have patched the vulnerabilities.
Yahoo! Mail XSS:
Before Cheng discovered this vulnerability, Yahoo! Mail filtering engine could block “expression()” syntax in a CSS attribute using a comment to break up expression( expr/* */ession() ). I used [0x81] with the following asterisk to make a sequence, so that the second */ would close the comment. But the filtering engine considered the first two comment symbol as a pair.
Content-Type: text/html; charset=GB2312
This exploitation is almost the same as the example.php.
Content-Type: text/html; charset=SHIFT_JIS
<font face="[0x81]"></font><font face=" onmouseover=alert() s=[0x81]">exploited</font>