Non-standard parsing behavior of strings in CSS expressions in
Internet Explorer could allow a clever attacker to escape the string
and execute arbitrary JavaScript via CSS. The three CSS properties
that HTML Purifier enabled that take strings as inputs are
background-image
, background
and
font-family
; instances of HTML Purifier that did not
enable these properties were not vulnerable.
This vulnerability was reported privately to the vendor by Mario Heiderich. Takeshi Terada was consulted during the construction of the fix. David Ross of the Internet Explorer team was separately informed of this class of exploits. Shortly prior to the release of 4.1.1, a post to sla.ckers.org was made to sanity check the new proposed fix. No active exploits are currently known.
Fix
There are several quirks in Internet Explorer's parsing of string-like expressions in CSS that caused this security vulnerability. They are as follows:
- Internet Explorer treats the second instance of an unprotected exclamation mark as a valid ending delimiter for its CSS parser (no semicolon is necessary in this case), and
- Internet Explorer does not recognize CSS escape characters
\"
and\'
in strings.
Thus, the original implementation of url()
in
background-image
and friends was vulnerable
because it did not use quoting and relied on character escaping, and
the original implementation of font-family
was vulnerable
because it expected to be able to escape internal apostrophes in its
string. The initial fix merely added quoting to url()
but failed to address Internet Explorer's broken character escaping.
At this point, there appeared to be a problem: it seemed impossible to express the full range of permitted URLs and font names: the characters that Internet Explorer did not seem to be able to escape were also valid characters in URLs and font names.
URLs were resolved in the following manner: while a single quote was a
valid character for a URL, a double quote was not. A backslash was
never a valid character. Thus, if the url("...")
form
was used, no escaping would be necessary.
Font names were resolved in a similar fashion (apostrophes are far
more common in font names than double quotes), but with an extra
observation made by Takeshi Terada: while Internet Explorer did not
support \"
style character escapes, it did support
hexadecimal character escapes. Thus, quotes and backslashes could be
portably preserved in font names.
History
The vulnerability was reported on April 25, 2010 via email. The first incorrect patch was committed to the public repository on April 26, 2010 with the summary: “Always quote the contents of url() in CSS.” HTML Purifier 4.1.0 was released on April 26, 2010.
On April 27, 2010, Mario Heiderich realized that the fix was insufficient. A long private discussion ensued on possible fixes, but we were unable to determine a solution that would not invalidate previously valid CSS expressions.
On May 20, 2010, I contacted Takeshi Terada and we came up with a feasible solution. A patch was committed on June 1, 2010 with the summary “Rewrite CSS url() and font-family output logic.” HTML Purifier 4.1.1 was released on June 1, 2010.
The HTML Purifier team realizes that the month long interval between the discovery of the second security vulnerability and the fix was not ideal, and hopes to maintain a fast turnaround for security vulnerabilities in the future.