CSS Quoting Full Disclosure

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:

  1. 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
  2. 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.