Clickjacking Google

When testing some x-frame-options behavior, I noticed that sameorigin cares about the top location, but not the parent location. At first I thought I discovered this, but turns out it’s not a brand new issue, and others have talked about it at least here and here.

It wasn’t immediately clear to me what sites were impacted, but two conditions need to be present: 1) somewhere on the victim domain, they need to allow you to frame stuff and 2) the victim domain uses x-frame-options sameorigin as a mitigation against clickjacking. With number two, most websites tend to not protect against clickjacking at all (which is worse, of course). However, there are a few places where these two conditions seem pretty pervasive. Google is the first thing that comes to mind because it’s common for Google to protect from clickjacking with x-frame-options: sameorigin, but then they allow external framing on the same domain. Using this and a little social engineering you can do some pretty nasty things, like an unprivileged Google Apps user taking over a domain.

A Couple Specific Examples

I have a pull request into BeEf for a module that my wife and I wrote which makes implementing these attacks trivial. I’ll probably do a blog post specifically about the module soon.

Attack 1: Making a Private Google Site Public

Here’s a video of Attack 1 in action, where victim Google site “besttest42” visits an attacker’s Google site “webstersprodigy” and inadvertently makes their site public by clicking on the next quote button a couple times (three to be exact)

Attack 2: unprivileged Google Apps user escalating to admin

  • Victim is logged in to a Google account.
  • Victim is social engineered to visit a “Google In-Page analytics” page that’s framing attacker controlled content (http://hacker.com). There seem to be a few other ways to frame attacker controlled content on google.com, such as igoogle or other things that might accept Google gadgets.
  • http://hacker.com can now frame a bunch of pages from google.com. Some targets are easier than others. Calendar is tough, for example, because it requires Javascript but also has a frame breaker. Others, like finance and reader, are easy. For my PoC, I framed the Google apps admin portal imagining the victim is a Google Apps admin and the attacker is an unprivileged apps user attempting to escalate priveleges. In this case, the attacker frames https://www.google.com/a/cpanel/webstersprodigy.net/Organization?userEmail=evilattacker@webstersprodigy.net
  • At this point there are four clicks involved. Click on “Roles and Privileges”, then “Assign more roles”, then “Super Admin” then “Confirm Assignment”.
  • I have a PoC for this as well as attack 1, but it’s more flaky because Google analytics Javascript sometimes made my clicks slightly off, and one click in particular I couldn’t completely hide (although I suspect with more time it should be possible). I admit the Google analytics route I have a PoC for would be tough to pull off in the real world (victim has to have recently logged in to admin portal, they have to click things inside of analytics) but the payoff is huge. The attacker is now an admin for a Google apps business and can do things like change a password and then read anyone’s email.

With attack 2, what we’re tricking the user to eventually click on is this:

Recommended Mitigations

I’m sure I’m not close to catching all the specific instances. It would probably be good for Google to go through most portals where users can change settings and set them to x-frame-options deny. A lot of these probably don’t need to be framed at all, and setting it to deny would stop the attack.

It would also be cool if Chrome checked the parent (and not just the top) when x-frame-options same-origin is set. Most browsers (Firefox, Safari, IE8) seem to do the same thing, but it seems wrong to me. It should be noted that IE9 and IE10 do better than this by checking the frame chain (e.g. this attack would fail with IE9).

Discosure Stuff

I contacted Google with basically the post above s/Google/you guys/ on 8/26. Here’s their response:

Thanks for your detailed report. Clearly, you understand some of the
challenges here ;)

This is something we’re aware of and there’s work going on amongst the
various browser vendors to modify (and agree on) what the right behaviour
should be. Right now, our approach is to bank on the browsers fixing this
in a more robust fashion.

I agree with this in principle. However, I would have liked to see x-frame-options deny set on the more sensitive pages. There are other UI redressing attacks possible of course, but since these require a few clicks I think using framing is by far the easiest. When I asked if they considered this a vuln or if they had any concerns about me writing about it, they wrote back:

No, it doesn’t qualify under the VRP — it’s something that we’re already
aware of. Feel free to write about it — it’s not especially widely known,
though is certainly not secret.

Google Docs Billion Laughs

This is a writeup of a bug (now fixed) I reported to Google last year.

A billion laughs attack was present in the Google Docs document parser. When the engine would parse a document it would resolve internal entities by expanding them. This eventually earned me a spot on the Google Wall of Sheep, but alas, no reward because it’s a DoS bug and DoS bugs don’t qualify.

With any type of DoS bug on a large service, it’s fairly difficult to determine the exact severity. There might be things that mitigate this somewhat, like there is probably throttling, the APIs might restrict on a per user basis, etc. Regardless, with one request it’s likely that it could tie up a processor for some amount of time (evidence suggests at least a couple minutes, but I suspect a lot more). This was clearly a bug; Google Docs was resolving internal entities without limit which is a CPU intensive operation and requires very little client processing/bandwidth.

Here’s a link 17th order billion laughs document: test17. Unzip and look in content.xml. To increase order of attack, change the entity it points to (eg &a19;, &a20, etc). The attack itself is very straightforward, and for those who don’t want to look at the doc, it just looks something like this, generated mostly from a legitimate ODT file:

<!--?xml version="1.0" encoding="UTF-8"?-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE billion [
  <!ENTITY a0 "Bomb!">
  <!ENTITY a1 "&a0;&a0;">
  <!ENTITY a2 "&a1;&a1;">
...
  <!ENTITY a25 "&a24;&a24;">
]>
...
<text:p text:style-name="Standard">Test &a17;</text:p>

Here are some interesting metrics on various laugh sizes:

  • 16th order took about 4 seconds for the app to return
  • 17th order took about 8 seconds for the app to return
  • 18th order took about 20 seconds and the upload is eventually rejected, after several empty files are created with the same name
  • 20th order took about 1:20 and the upload is eventually rejected, dozens of empty files are created (I’m not sure what was going on with that).
  • 21st order never seemed to “finish”

One quick note is I never found anywhere that external entities were resolved. It’s hard to tell for sure because certain egress/chroot-type mitigations could have just helped make this hard to exploit. Correct or not, I sort of suspected the external entity thing might not be a problem. Openoffice resolved internal but not external entities, so (right or wrong) I guessed that it’s somewhat likely that Google is re-using or at least sort of mimicking openoffice’s document parser.

The reporting process was fairly nighmarish, but I put the blame mostly on MSVR rather than Google… not to point fingers, all I know is I never heard much of anything back.

In any serious service I think DoS bugs get a bad rap. I’ve met a lot of people who consider DoS bugs as low severity just based on that classification alone. In reality, I think people tend to care a lot more about when an online service is unavailable. When Sony did everything terribly, did most people care about the data they lost? Some did (I did), but I think most just wanted to start playing games again already. So what’s more severe? A clickjacking bug in Facebook that allows you to do a targeted attack to take over someone’s account, or a DoS bug that can bring down Facebook?

With some imagination, I wonder if something like this could have been used in the right (wrong?) hands to bring down a service as large as Google Docs.