Playing With iframes: Bypassing Content-Security-Policy
Hi fellow hackers and bug bounty hunters! I’m JM Sanchez, and today I’ll be sharing how I found my first bug in a bug bounty program. I hope you’ll learn something or at least be entertained about the story I will be telling in a few seconds.
[UPDATE] Report is now available on Hackerone. Click Here to View
I will be temporarily naming it
company.com, because I’m still not allowed to disclose any further details about this program.
company.com has features that lets you customize a template with drop-down widgets, HTML editor, or a mix of both.
In a mind of a hunter, this is an easy HTML Injection, or even XSS (Cross-Site-Scripting). We don’t have to worry about escaping out of attributes and such things because there is already an HTML Editor built for that.
Of course, the site is running a bug bounty program and is at least aware of common security vulnerabilities. That is why they implemented CSP (Content-Security-Policy) that limits which resources can be included by the user in the template.
The CSP prohibits us from executing inline or remote
I tried to host a malicious page in my localhost, then forwarded it with
ngrok. Then I inserted an
iframe tag to the template
It’s blocked, how sad.
Then I changed the
src of the
iframe to company.com
It returned the homepage as expected. At this point, I assumed that iframes can be sourced only from the company.com domain. However, I was proven wrong. It only took me 2 key presses to find the solution. Surprise surprise, it’s
I found the culprit of the filter. In
<meta http-equiv=”Content-Security-Policy” content=”…”>, I found this
frame-src data: *.firebaseapp.com *.█████.com *.google.com *.facebook.com 'self';
Iframes in the page are only allowed from *.firebaseapp.com, *.█████.com, *.google.com, *.facebook.com, and from the company.com domain.
When I saw this, I knew it’s going to be exploitable.
*.firebaseapp.com is FREE. Anyone can just host static html pages in here. So I quickly searched up how to host my page in firebaseapp. Turns out it requires nodeJS, so I quickly installed one then followed steps to deploy my page.
I now own
hackerone-jm.firebaseapp.com, a sub-domain included in the
*.firebaseapp.com wildcard. Then I inserted it using an iframe
Boom! It works. CSP is now bypassed and we can include my own page in the iframe.
What can iframes do? It can’t even access the parent’s cookies! All of CSP bypass for nothing!
Well, the statement above is half true. It is true that since my page in
firebaseapp.com and company.com do not share the same domain, they also do not share cookies. Cookies can be sent from domain to its subdomain, but not to others.
company.com -> parent window
hackerone-jm.firebaseapp.com -> child (iframe)
Well, iframes are naughty children, they can mess with their parents most of the time if not given proper counter-measures. I watch anime in pirated streaming sites, and one thing all of us will remember are those annoying pop-ups and redirects. This is what inspired my findings
From a simple iframe injection, I upgraded mine to an open redirect. I placed the code below in
top.location = 'https://www.attacker.com';
I successfully escaped from the iframe. Everytime the iframe is loaded, the whole page including company.com will redirect and there can even be a popup window.
document.location will redirect the current page it is hosted in, but
top.location will redirect even the outermost parent.
[+] Phishing against other users
Triaged after 3 days