Wednesday, January 19, 2011

A harmless SVG + XSLT curiousity

How do you execute code in a turing complete language via the <img> tag? Why, by combining an XSL transform into an SVG image of course!

I stumbled across this old file in my archives:

http://cevans-app.appspot.com/static/expensive_xsl_svg.html

If you run it e.g. in Chrome, it'll consume a load of CPU (and subsequently memory if you let it crank). I expect it'll do the same in any WebKit browser, and Opera's error message implies it has all the pieces to follow suit if I tweaked the file a bit.

It's not a significant security issue, but it's an interesting quirk. It works because SVG and XSL are both XML formats, and XSL can use a self-referential construct to operate on itself as the input document:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="#stylesheet"?>

If the XSL output XML is valid SVG syntax, then it will render. So you can probably pull some crazy tricks to generate a complicated SVG on the fly! My sample file doesn't get that far; it simply deliberately runs an expensive stylesheet transform with a large output.

If anyone wanted to play with this, there may be interesting issues with the unusual context the XSL is executing in. What if you used xsl:import or the document() XPath function? What origin is used for security checks?, etc.

Thursday, October 21, 2010

Minor leak, major headache

I find this bug interesting, because at first it looks like a relatively minor cross-origin leak. But with a bit of investigation, it has major consequence.

The bug is specific to Internet Explorer, and still seems unfixed (in stable versions) at the time of writing. I told Microsoft about it back in 2008. Therefore this disclosure is not an 0-day, but more like a 600-day.

The bug is pretty simple: IE supports a window.onerror callback which fires whenever a Javascript parse or runtime error occurs. Trouble is, it fires even if www.evil.com registers its own window.onerror handler and then uses <script src="http://www.bank.com/">. We'll demonstrate the consequence of this later.

The bug has a very interesting history, which is worth briefly outlining here:
So why is this a serious bug? Well, Javascript error messages are usually pretty terse but in at least one case, cross-origin content is echoed back to the attacker: variable names. e.g. 'blah' is not defined.

So if the cross-origin text looks like a Javascript variable reference, then the attacker has a very useful leak!

Here is a proof-of-concept against Google Reader, which works by stealing cross-origin content which happens to be an anti-XSRF token:

http://scary.beasts.org/misc/reader.html

As it happens, the Reader product deployed a change which detects the vulnerable User-Agent string (Internet Explorer) and uses a workaround. So the PoC is neutered. This is a shame because the PoC used to force your friend to subscribe to a goat-farming feed against their will. For now, you'll have to locate an alternate attack vector for this vulnerability -- do let me know what you find via a comment.

It's worth closing with some notes that this area is ripe for further research. There are a varied number of text structures which can be stolen (iteratively if necessary) with this trick:
  • a,b,c -- i.e. the CSV syntax
  • The b in a:b
  • a.b.c
  • The b in {a:b}
  • Expression constructs such as a/b/c
  • Constructs like the above, if wrapped in () or [] etc.
To experiment with what Javscript error message you might see with a given piece of cross-origin text, you can use:

http://scary.beasts.org/misc/onerr.html

(Only works in browsers with window.onerror, such as IE).

Please leave a comment if you have more constructs which can be stolen; or more examples of sites where stuff can be stolen from.

Wednesday, September 29, 2010

IE8 CSS-based forced tweeting

A few weeks back, I published a demo that uses a serious Internet Explorer cross-origin violation to permit a malicious web page to force the visitor to make unwarranted tweets:

http://seclists.org/fulldisclosure/2010/Sep/64

The post was light on technical details of how the attack works, so they will be filled in below. In addition, I'll quickly take care of the FAQ:

Q) Does this attack affect earlier versions of Internet Explorer, such as IE6?
A) Yes, the attack works verbatim on IE6 in my testing.

Q) When will a patch be available?
A) As far as I'm aware, Microsoft have not stated when users of IE6, IE7 and IE8
will be afforded protection. I'm not privy to any other details.

Q) Why drop this 0-day?
A) The rampant misuse of the term "0-day" is somewhat disappointing. You can look
it up on Wikipedia, but an "0-day" is a term reserved for a disclosure where the
vendor was previously unaware of it. In this instance, the bug is better described
as a "500+ day" if you look at when the bug was first publicly disclosed.

So how does the Twitter attack work?
When exploiting this bug in general, you are looking to meet various conditions:

  • Finding a text injection point in the target origin to start a CSS property.

  • Using a text injection context that does not escape vital CSS characters.

  • Arranging for some sensitive information (such as an anti-XSRF token) to appear after the text injection point.

  • Arranging that no CSS property terminator appears before the sensitive information.

In the Twitter attack, the injection point can clearly be seen; it's simply the text of a tweet in my "scarybeaststest" account:

http://twitter.com/scarybeaststest

If you look at the raw source HTML of that page on twitter.com, you'll see the following piece of HTML:

<span class="entry-content">{}body{font-family:"</span>

That's the start of a CSS descriptor injected into the Twitter page. Note that none of the characters {, }, : or " need to be escaped in the HTML tag value context -- there is no Twitter bug here.

The need for the " character in this injection context is subtle: it derives from how the IE CSS parser determines end-of-property. Essentially, IE is just looking for a ; character to denote the end of the value for the "font-family" property. Unluckily for us, the ; character appears in the Twitter HTML prior to the high-value anti-XSRF secret we are trying to steal. This would tend to terminate the injected CSS property early and spoil our day. Fortunately, ; is perfectly acceptable within a quoted section, so the use of " will ensure the stray ; characters appear between a pair of quotes and do not terminate the parse of our CSS property.

With our injection, the Twitter page ends up looking a little bit like:

<html>bla..bla..{}body{font-family:"..more HTML prop="value" some ; SECRET_XSRF_TOKEN blah EOF

The IE CSS parser keeps track of opening and closing quote pairs, and only terminates the CSS property if a ; is encountered outside of quoting. Our usage of a " character to start the property ensures that any ; characters appear within the quoted context. Eventually, the CSS parser includes the secret anti-XSRF token in the CSS property value and then hits EOF with an unterminated quote. IE happily recovers from this situation by constructing a CSS property value with all the text parsed so far!

So the attacker simply includes the above CSS-property-injected Twitter page as CSS and recovers the CSS value for the "font-family" property, which includes the secret token (as well as a bunch of quoted semi-colons and other HTML detritus which is less interesting to us).

There is quite a pile of IE CSS parsing bugs involved to pull this off. Many are CSS specification violations:

  1. Newlines permitted within quoted strings.
  2. Whitespace permitted outside quoted strings.
  3. Multiple quoted strings permitted in single property.
  4. End of file within quoted string does not invalidate descriptor.
  5. Bad Content-Type and non-CSS content ignored for cross-origin CSS.
As be seen, the interaction of CSS property terminator vs. quoting context is quite subtle. There might well be a simpler twitter.com injection to use, but this more complicated example is simply the first working one I found.

Wednesday, August 4, 2010

Internet Explorer considered harmful

Now that this paper is officially public, the full story of CSS-based cross-origin theft can come out. (As an aside I'd like to note that I contributed little other than review to the paper so credit must go to the other named individuals).

For background reading, see my Dec 2009 original post and an update that notes Firefox fixing the issue.

In the original post, I state two mitigating factors that prevent the attack being very serious: the fact that quotes and particularly newlines stop the attack from working due to the way CSS parsing is specified.

It turns out that Internet Explorer is not compliant in either of these aspects, leaving it more vulnerable that the other browsers. Not only is it the most vulnerable, but it is also the only browser to not have a fix available for its latest stable version. Fully patched IE8 is still vulnerable.

For an example of how easily data can be stolen cross-origin, try this demo in IE:

http://sh0dan.org/css.html

It uses the font-family CSS property to steal all text from the injection point up to the next ; character. Alternatively, to get more control, we can use background-image:url( which will steal all text from the injection point up to the next ); sequence (which can be useful as it is less likely to occur by 'accident').

I have PoCs which will steal your webmail's XSRF token, with follow-on loss of account integrity and confidentiality. It's a nasty attack: e-mail someone a link and if they click it, they are owned with a pure browser cross-origin bug. I don't think it would be productive to share any PoCs at this time.

Talking to some greyhats, I was surprised to learn this bug has been public since at least 2008. If you speak Japanese, see:

http://d.hatena.ne.jp/ofk/20081111/1226407593

That's a dangerously long time for such a bug to be live and known by hackers.

Browsers are complicated pieces of software and will always have bugs. Time-to-fix therefore matters for a browser. If security is a factor in your browser choice, I recommend you look at Opera or Chrome. These browsers fixed this bug the fastest.

Thursday, July 22, 2010

Firefox fixes CSS-based cross-origin theft issue

Firefox just released version 3.6.7 of their excellent browser, and it fixes this:

http://www.mozilla.org/security/announce/2010/mfsa2010-46.html

This leaves 4 of the 5 major browsers with fixes (more on this in an upcoming post), which is my threshold for documenting a little tweak to exploitability. It is partially inspired by Gareth Heyes' attack on E4X using character set overrides. For interesting background reading, see:

http://www.thespanner.co.uk/2009/02/24/inline-utf-7-e4x-javascript-hijacking/

Turns out, the same character set override applies to loading cross-origin CSS via the <link> tag. This means that you can use UTF7 in Firefox to get around one of the key restrictions in the original attack. Specifically, you can force the CSS to be interpreted as UTF7, which makes injecting either type of quote (single or double) trivial to do without it getting escaped. Of course, the larger newline-related restriction remains in sane browsers.

Also, it's worth documenting how the character set override works. Interestingly, in all the browsers I tested (Chrome, Firefox, Safari) -- any character set specified in a site's HTTP headers has a higher precedence that the attacker's attempted override in the <link> tag. Useful. You should always specify character sets where possible. It has also defended against other previously unknown attacks in the past.

One final note is that not all browsers support UTF7. Chrome for example does not. I'm sure no-one would shed tears if UTF7 died.

Tuesday, July 20, 2010

Fixing responsible disclosure

Today I had the pleasure to post:

http://googleonlinesecurity.blogspot.com/2010/07/rebooting-responsible-disclosure-focus.html

It is co-signed by some of my awesome fellow engineers who personally believe in what is written.

Recent discussions and debates have shown that "responsible disclosure" is broken. It is badly named and ill-defined. Possibly the worst problem with responsible disclosure is that is permits known critical vulnerabilities to go unfixed for months or even years. As many commentators have pointed out, that is hardly "responsible". We've also seen what happens when we go down that route.

The simple proposed fix is to use reasonable deadlines to encourage things in the right direction. 60 days for critical issues. ("critical" in the genuine unsandboxed & arbitrary code execution sense, not "critical" just because some news article or researcher is overstating things).

Speaking personally about my work on securing the Chromium browser: I'd be mortified if I learned of a SecSeverity-Critical bug and it took me over 60 days to protect my users from it. It's not always possible to move this fast, but for one of the few critical bugs I found, the timeline shows it was not only fixed but also installed across the user base in about 6 days.

Related reading:

More money for critical Chromium security bugs!

We've seen who is $1337 but who is $3133.7 ?

I just launched this:
http://blog.chromium.org/2010/07/celebrating-six-months-of-chromium.html

I've really enjoyed launching and now refreshing this program.