busting-frame-busting-a-study-of-clickjacking-vulnerabilities-on-popular-sites-slides
busting-frame-busting-a-study-of-clickjacking-vulnerabilities-on-popular-sites-slides
busting-frame-busting-a-study-of-clickjacking-vulnerabilities-on-popular-sites-slides
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
What is <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g>?
What is <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g>?<br />
• HTML allows for any site to <str<strong>on</strong>g>frame</str<strong>on</strong>g> any URL with an IFRAME<br />
(internal <str<strong>on</strong>g>frame</str<strong>on</strong>g>)<br />
<br />
Ignored by most browsers<br />
What is <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g>?<br />
• Frame <str<strong>on</strong>g>busting</str<strong>on</strong>g> are techniques for<br />
preventing framing by the <str<strong>on</strong>g>frame</str<strong>on</strong>g>d site.
What is <str<strong>on</strong>g>frame</str<strong>on</strong>g><str<strong>on</strong>g>busting</str<strong>on</strong>g>?<br />
Comm<strong>on</strong> <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g> code is made<br />
up <str<strong>on</strong>g>of</str<strong>on</strong>g>:<br />
• a c<strong>on</strong>diti<strong>on</strong>al statement<br />
• a counter acti<strong>on</strong><br />
if (top != self) {<br />
top.locati<strong>on</strong> = self.locati<strong>on</strong>;<br />
}
Why <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g>?
Primary: Clickjacking<br />
Jeremiah Grossman and Robert Hansen, 2008
Clickjacking 2.0<br />
(Paul St<strong>on</strong>e, BHEU ‘10)<br />
Utilizing drag and drop:<br />
Grab data <str<strong>on</strong>g>of</str<strong>on</strong>g>f the page<br />
(including source code, form data)<br />
Get data into the page<br />
(forms etc.)<br />
Fingerprint individual objects in the <str<strong>on</strong>g>frame</str<strong>on</strong>g>d<br />
page
Survey<br />
• Idea: Grab <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g> from Alexa<br />
Top-500 and all US banks.<br />
Analyze code.<br />
• Used semi-automated crawler based<br />
<strong>on</strong> HTMLUnit.<br />
• Manual work to trace through<br />
obfuscated and packed code.
Obfuscati<strong>on</strong>/Packing<br />
�
Survey<br />
Sites Frame<str<strong>on</strong>g>busting</str<strong>on</strong>g><br />
Top 10 60%<br />
Top 100 37%<br />
Top 500 14%
Survey<br />
C<strong>on</strong>diti<strong>on</strong>al Statements<br />
if (top != self)<br />
if (top.locati<strong>on</strong> != self.locati<strong>on</strong>)<br />
if (top.locati<strong>on</strong> != locati<strong>on</strong>)<br />
if (parent.<str<strong>on</strong>g>frame</str<strong>on</strong>g>s.length > 0)<br />
if (window != top)<br />
if (window.top !== window.self)<br />
if (window.self != window.top)<br />
if (parent && parent != window)<br />
if (parent &&<br />
parent.<str<strong>on</strong>g>frame</str<strong>on</strong>g>s &&<br />
parent.<str<strong>on</strong>g>frame</str<strong>on</strong>g>s.length>0)<br />
if((self.parent&&<br />
!(self.parent===self))&&<br />
(self.parent.<str<strong>on</strong>g>frame</str<strong>on</strong>g>s.length!=0))
Counter-Acti<strong>on</strong> Statements<br />
top.locati<strong>on</strong> = self.locati<strong>on</strong><br />
top.locati<strong>on</strong>.href = document.locati<strong>on</strong>.href<br />
top.locati<strong>on</strong>.href = self.locati<strong>on</strong>.href<br />
top.locati<strong>on</strong>.replace(self.locati<strong>on</strong>)<br />
top.locati<strong>on</strong>.href = window.locati<strong>on</strong>.href<br />
top.locati<strong>on</strong>.replace(document.locati<strong>on</strong>)<br />
top.locati<strong>on</strong>.href = window.locati<strong>on</strong>.href<br />
top.locati<strong>on</strong>.href = "URL"<br />
document.write(’’)<br />
top.locati<strong>on</strong> = locati<strong>on</strong><br />
top.locati<strong>on</strong>.replace(document.locati<strong>on</strong>)<br />
top.locati<strong>on</strong>.replace(’URL’)<br />
top.locati<strong>on</strong>.href = document.locati<strong>on</strong><br />
top.locati<strong>on</strong>.replace(window.locati<strong>on</strong>.href)<br />
top.locati<strong>on</strong>.href = locati<strong>on</strong>.href<br />
self.parent.locati<strong>on</strong> = document.locati<strong>on</strong><br />
parent.locati<strong>on</strong>.href = self.document.locati<strong>on</strong><br />
top.locati<strong>on</strong>.href = self.locati<strong>on</strong><br />
top.locati<strong>on</strong> = window.locati<strong>on</strong><br />
top.locati<strong>on</strong>.replace(window.locati<strong>on</strong>.pathname)<br />
window.top.locati<strong>on</strong> = window.self.locati<strong>on</strong><br />
setTimeout(functi<strong>on</strong>(){document.body.innerHTML=’’;},1);<br />
window.self.<strong>on</strong>load = functi<strong>on</strong>(evt){document.body.innerHTML=’’;}<br />
var url = window.locati<strong>on</strong>.href; top.locati<strong>on</strong>.replace(url)
All <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g> code we found<br />
was broken.
Let’s check out some code.
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g> Walmart<br />
if (top.locati<strong>on</strong> != locati<strong>on</strong>) {<br />
}<br />
if(document.referrer &&<br />
document.referrer.indexOf("walmart.com") == -1)<br />
{<br />
}<br />
top.locati<strong>on</strong>.replace(document.locati<strong>on</strong>.href);
Error in Referrer Checking<br />
From http://www.attacker.com/walmart.com.html<br />
<br />
Limit use <str<strong>on</strong>g>of</str<strong>on</strong>g> indexOf()…
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g><br />
if (window.self != window.top &&<br />
{<br />
}<br />
!document.referrer.match(<br />
/https?:\/\/[^?\/]+\.nytimes\.com\//))<br />
self.locati<strong>on</strong> = top.locati<strong>on</strong>;
Error in Referrer Checking<br />
From http://www.attacker.com/a.html?b=https://www.nytimes.com/<br />
<br />
Anchor your regular expressi<strong>on</strong>s.
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g><br />
if (self != top) {<br />
}<br />
var domain = getDomain<br />
(document.referrer);<br />
var okDomains = /usbank|localhost|usbnet/;<br />
var matchDomain = domain.search<br />
(okDomains);<br />
if (matchDomain == -1) {<br />
}<br />
//<str<strong>on</strong>g>frame</str<strong>on</strong>g> bust
Error in Referrer Checking<br />
From http://usbank.attacker.com/<br />
<br />
D<strong>on</strong>’t make your regular expressi<strong>on</strong>s too lax.
Strategic Relati<strong>on</strong>ship?<br />
Norweigan State House Bank<br />
http://www.husbanken.no
Strategic Relati<strong>on</strong>ship?<br />
Bank <str<strong>on</strong>g>of</str<strong>on</strong>g> Moscow<br />
http://www.rusbank.org
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g><br />
try{<br />
A=!top.locati<strong>on</strong>.href<br />
}catch(B){}<br />
A=A&&<br />
!(document.referrer.match(/^https?:\/\/[-az09.]<br />
*\.google\.(co\.|com\.)? [a-z] +\/imgres/i))&&<br />
!(document.referrer.match(/^https?:\/\/([^\/]*\.)?<br />
(myspace\.com|<br />
myspace\.cn|<br />
simsidekick\.com|<br />
levisawards\.com|<br />
digg\.com)\//i));<br />
if(A){ //Framebust }
The people you trust might not<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g> bust<br />
Google Images does not <str<strong>on</strong>g>frame</str<strong>on</strong>g>bust.
Referrer = Funky Stuff<br />
Many attacks <strong>on</strong> referrer: washing/changing<br />
Open redirect referrer changer<br />
HTTPS->HTTP washing<br />
Can be hard to get regular expressi<strong>on</strong> right<br />
(apparently)<br />
“Friends” cannot be trusted
Facebook Dark Layer
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g> Facebook<br />
• Facebook deploys an exotic variant:<br />
if (top != self) {<br />
try {<br />
if (top.locati<strong>on</strong>.hostname.indexOf("apps") >= 0) throw 1;<br />
} catch (e) {<br />
window.document.write("<br />
");<br />
}<br />
}
Facebook – Ray <str<strong>on</strong>g>of</str<strong>on</strong>g> Light!<br />
All Facebook c<strong>on</strong>tent is centered! We can<br />
push the c<strong>on</strong>tent into the ray <str<strong>on</strong>g>of</str<strong>on</strong>g> light<br />
outside <str<strong>on</strong>g>of</str<strong>on</strong>g> the div.<br />
<br />
<br />
window.scrollTo(10200, 0 ) ;<br />
Facebook – Ray <str<strong>on</strong>g>of</str<strong>on</strong>g> Light!
Let’s move <strong>on</strong> to some<br />
generic attacks!
Courtesy <str<strong>on</strong>g>of</str<strong>on</strong>g> many<br />
if(top.locati<strong>on</strong> != self.locati<strong>on</strong>) {<br />
}<br />
parent.locati<strong>on</strong> = self.locati<strong>on</strong>;
Double Framing!<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g>d1.html<br />
<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g>d2.html<br />
Descendent Policy<br />
• Introduced in Securing <str<strong>on</strong>g>frame</str<strong>on</strong>g> communicati<strong>on</strong> in browsers.<br />
(Adam Barth, Collin Jacks<strong>on</strong>, and John Mitchell. 2009)<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g>d1.html<br />
<br />
Descendant Policy<br />
A <str<strong>on</strong>g>frame</str<strong>on</strong>g> can navigate <strong>on</strong>ly it’s decedents.<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g>d2.html<br />
top.locati<strong>on</strong> = self.locati<strong>on</strong> is always okay.<br />
Locati<strong>on</strong> Clobbering<br />
if (top.locati<strong>on</strong> != self.locati<strong>on</strong>) {<br />
}<br />
top.locati<strong>on</strong> = self.locati<strong>on</strong>;<br />
If top.locati<strong>on</strong> can be changed or<br />
disabled this code is useless.<br />
But our trusted browser would never let<br />
such atrocities happen… right?
Locati<strong>on</strong> Clobbering<br />
IE 7: IE 7:<br />
var locati<strong>on</strong> = “clobbered”;<br />
Safari:<br />
window.__defineSetter__("locati<strong>on</strong>", functi<strong>on</strong>(){});<br />
top.locati<strong>on</strong> is now undefined. �<br />
http://code.google.com/p/ browsersec/wiki/Part2#Arbitrary_ page_mashups_(UI_redressing)
Asking Nicely<br />
• User can manually cancel any<br />
redirecti<strong>on</strong> attempt made by<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g><str<strong>on</strong>g>busting</str<strong>on</strong>g> code.<br />
• Attacker just needs to ask…<br />
<br />
window.<strong>on</strong>beforeunload = functi<strong>on</strong>() {<br />
}<br />
return ”Do you want to leave PayPal?";<br />
<br />
Asking Nicely
Not Asking Nicely<br />
• Actually, we d<strong>on</strong>’t have to ask nicely<br />
at all. Most browser allows to cancel<br />
the relocati<strong>on</strong> “programmatically”.<br />
var prevent_bust = 0<br />
window.<strong>on</strong>beforeunload = functi<strong>on</strong>() {kill_bust++ }<br />
setInterval(functi<strong>on</strong>() {<br />
if (kill_bust > 0) {<br />
kill_bust -= 2;<br />
}<br />
}, 1);<br />
window.top.locati<strong>on</strong> = 'http://no-c<strong>on</strong>tent-204.com'<br />
<br />
http://coderrr.wordpress.com/2009/02/13/preventing-<str<strong>on</strong>g>frame</str<strong>on</strong>g>-<str<strong>on</strong>g>busting</str<strong>on</strong>g>-and-click-jacking-ui-redressing
• IE 8:<br />
Restricted z<strong>on</strong>es<br />
<br />
Javascript and Cookies disabled<br />
• Chrome (HTML5):<br />
<br />
Javascript disabled (cookies still there)<br />
• IE 8 and Firefox:<br />
designMode = <strong>on</strong> (Paul St<strong>on</strong>e BHEU’10)<br />
Javascript disabled (more cookies)
Reflective XSS filters<br />
• Internet Explorer 8 introduced reflective<br />
XSS filters:<br />
http://www.victim.com?var= alert(‘xss’)<br />
If alert(‘xss’); appears in the rendered<br />
page, the filter will replace it with alert<br />
(‘xss’)
Reflective XSS filters<br />
Can be used to target <str<strong>on</strong>g>frame</str<strong>on</strong>g> <str<strong>on</strong>g>busting</str<strong>on</strong>g><br />
(Eduardo Vela ’09)<br />
Original<br />
if(top.locati<strong>on</strong> != self.locati<strong>on</strong>) //<str<strong>on</strong>g>frame</str<strong>on</strong>g>bust <br />
Request > http://www.victim.com?var= if (top<br />
Rendered<br />
if(top.locati<strong>on</strong> != self.locati<strong>on</strong>)<br />
Chrome’s XSS auditor, same problem.
Is there any hope?<br />
Well, sort <str<strong>on</strong>g>of</str<strong>on</strong>g>…
X-Frames-Opti<strong>on</strong>s (IE8)<br />
• HTTP header sent <strong>on</strong> resp<strong>on</strong>ses<br />
• Two possible values: DENY and<br />
SAMEORIGIN<br />
• On DENY, will not render in <str<strong>on</strong>g>frame</str<strong>on</strong>g>d<br />
c<strong>on</strong>text.<br />
• On SAMEORIGIN, <strong>on</strong>ly render if top<br />
<str<strong>on</strong>g>frame</str<strong>on</strong>g> is same origin as page giving<br />
directive.
X-Frames-Opti<strong>on</strong>s<br />
• Good adopti<strong>on</strong> by browsers (all but<br />
Firefox, coming in 3.7)<br />
• Poor adopti<strong>on</strong> by <strong>sites</strong> (4 out <str<strong>on</strong>g>of</str<strong>on</strong>g> top<br />
10,000, survey by sans.org)<br />
• Some limitati<strong>on</strong>s: per-page policy, no<br />
whitelisting, and proxy problems.
C<strong>on</strong>tent Security Policy (FF)<br />
• Also a HTTP-Header.<br />
• Allows the site to specific restricti<strong>on</strong>s/<br />
abilities.<br />
• The <str<strong>on</strong>g>frame</str<strong>on</strong>g>-ancestors directive can<br />
specifiy allowed <str<strong>on</strong>g>frame</str<strong>on</strong>g>rs.<br />
• Still in beta, coming in Firefox 3.7
Best for now<br />
(but still not good)<br />
html { visibility: hidden }<br />
<br />
if (self == top) {<br />
document.documentElement.style.visibility =<br />
'visible';<br />
} else {<br />
}<br />
top.locati<strong>on</strong> = self.locati<strong>on</strong>;<br />
… a little bit more.<br />
These <strong>sites</strong> (am<strong>on</strong>g others) do <str<strong>on</strong>g>frame</str<strong>on</strong>g>m<str<strong>on</strong>g>busting</str<strong>on</strong>g>…
… a little bit more.<br />
… but do these?
No, they generally d<strong>on</strong>’t…<br />
Site URL Frame<str<strong>on</strong>g>busting</str<strong>on</strong>g><br />
Facebook http://m.facebook.com/ YES<br />
MSN http://home.mobile.msn.com/ NO<br />
GMail http://m.gmail.com NO<br />
Baidu http://m.baidu.com NO<br />
Twitter http://mobile.twitter.com NO<br />
MegaVideo http://mobile.megavideo.com/ NO<br />
Tube8 http://m.tube8.com NO<br />
PayPal http://mobile.paypal.com NO<br />
USBank http://mobile.usbank.com NO<br />
First Interstate Bank http://firstinterstate.mobi NO<br />
NewEgg http://m.newegg.com/ NO<br />
MetaCafe http://m.metacafe.com/ NO<br />
RenRen http://m.renren.com/ NO<br />
MySpace http://m.myspace.com NO<br />
VK<strong>on</strong>takte http://pda.vk<strong>on</strong>takte.ru/ NO<br />
WellsFargo https://m.wf.com/ NO<br />
NyTimes http://m.nytimes.com Redirect<br />
E-Zine Articles http://m.ezinearticles.com Redirect
Summary<br />
• All <str<strong>on</strong>g>frame</str<strong>on</strong>g><str<strong>on</strong>g>busting</str<strong>on</strong>g> code out there can<br />
be broken across browsers in several<br />
different ways<br />
• Defenses are <strong>on</strong> the way, but not yet<br />
widely adopted<br />
• Relying <strong>on</strong> referrer is difficult<br />
• If JS is disabled, d<strong>on</strong>’t render the page.<br />
• Framebust your mobile <strong>sites</strong>!
Questi<strong>on</strong>s?<br />
rydstedt@stanford.edu