[XSS] Breaking ‘safe’ embeds via frame-src bypass

Overview

We pat ourselves on the back when our WAF blocks a classic <script> alert. But modern web applications are a tapestry of first-party code and third-party services. What happens when an attacker doesn't need to break your walls, but simply uses a door you left open for a trusted guest?


The Vulnerability
Let's set the scene. Your application, trusted-site.com, has secure server-side filters. It correctly neutralizes or blocks any user input containing <script>, onerror=, or other obvious XSS vectors. However, to support rich content, you allow certain HTML tags like <iframe> and <object>. These are necessary for embedding videos, maps, or other third-party widgets.

An attacker discovers this policy. They don't try to inject JavaScript directly. Instead, they inject a gateway:

<iframe src="https://vulnerable-widget-provider.com/page-with-xss.html" style="position:fixed;top:0;left:0;width:100vw;height:100vh;border:none;"></iframe>

Or, more advanced one:

<object data="https://vulnerable-widget-provider.com/page-with-xss.html" style="position:fixed;top:0;left:0;width:100vw;height:100vh;border:none;"></object>

The vulnerability is not a bug in your sanitizer; it's a flaw in the security model. You allowed a tag that can pull in arbitrary, untrusted external content. You are now only as secure as the least secure service you allow your users to embed. You can get the vulnerable third party site by using a lab site, or maybe create your own, that specifically vuln to XSS, You can use publicly vulnerable site like vulnweb by acunetix, etc. That way you can literally execute any code, cuz it's vulnerable to any code that get injected (not sanitized)

Fun fact: If you render a third‑party page that has an XSS, any payload you inject will execute there — you’re executing code in the third‑party origin simply by rendering its vulnerable content.

The Exploit
The attack chain is pretty straightforward:
  •  * The Injection: The attacker plants the malicious payload (<iframe> or <object>) into a field that renders HTML (e.g., a comment, forum post, or profile bio). Your filters allow it.
  •  * The Render: A victim logs into trusted-site.com and visits the page containing the payload.
  •  * The Load: The victim's browser, trusting trusted-site.com, loads the frame from vulnerable-widget-provider.com.
  •  * The Chain Reaction: The source URL for the iframe is carefully crafted to trigger a known XSS vulnerability on vulnerable-widget-provider.com. This could be a reflected XSS in a search parameter or a persistent XSS in a comment section.
  •  * The Payload Execution: The XSS payload on the third-party site executes. While it runs in the origin of vulnerable-widget-provider.com, the impact is felt by the user on trusted-site.com.
The resulting script can: 
* Render a perfect phishing overlay, stealing the user's credentials for trusted-site.com.
* Make fetch requests to the trusted-site.com API, performing actions on behalf of the victim.
* Hijack the user's session if cookies are not properly secured with HttpOnly.

The user never leaves trusted-site.com, yet they are completely compromised.

The Primary Defense: Content Security Policy (CSP)
The most effective defense against this attack is a Content Security Policy. A strong CSP acts as a whitelist for all content sources, rendering the attacker's injection useless.
A weak or non-existent CSP is an open invitation:
Vulnerable CSP (or none):
Content-Security-Policy: default-src 'self'

This policy does not restrict frames. The malicious iframe loads, and the attack proceeds.

Secure CSP (The Game-Changer):
Content-Security-Policy: default-src 'self'; frame-src 'self' https://trusted-youtube.com; object-src 'none'

This policy is a game-changer. It: * frame-src 'self' https://trusted-youtube.com: Explicitly states that frames can only be loaded from the application's own origin and one specific, vetted provider.
 * object-src 'none': Completely blocks the dangerous <object> tag, which is rarely needed for legitimate purposes.
With this CSP, the browser will refuse to load the iframe from vulnerable-widget-provider.com, breaking the attack chain at the first step.

Conclusion
This technique is not a speculative threat. It's a valid and high-impact finding that highlights a critical shift in perspective: your application's security perimeter includes every third-party service you embed. By locking down frame-src, object-src, and other directives, you move from a model of "allow all except what's bad" to "deny all except what's explicitly good".

Comments

Popular posts from this blog

About Me

[BYPASS] IKEv2 Fortinet Misconfiguration