# Iframes in XSS, CSP and SOP {{#include ../../banners/hacktricks-training.md}} ## Iframes in XSS 有3种方式来指示iframe页面的内容: - 通过`src`指示一个URL(该URL可以是跨源或同源) - 通过`src`使用`data:`协议指示内容 - 通过`srcdoc`指示内容 **访问父变量和子变量** ```html ``` ```html ``` 如果您通过 HTTP 服务器(如 `python3 -m http.server`)访问之前的 HTML,您会注意到所有脚本都会被执行(因为没有 CSP 阻止它)。**父级将无法访问任何 iframe 内部的 `secret` 变量**,**只有 if2 和 if3(被视为同站)可以访问原始窗口中的 secret**。\ 请注意 if4 被认为具有 `null` 来源。 ### 带 CSP 的 Iframes > [!TIP] > 请注意,在以下绕过中,响应的 iframed 页面不包含任何阻止 JS 执行的 CSP 头。 `script-src` 的 `self` 值将不允许使用 `data:` 协议或 `srcdoc` 属性执行 JS 代码。\ 然而,即使 CSP 的 `none` 值也将允许执行在 `src` 属性中放置 URL(完整或仅路径)的 iframes。\ 因此,可以通过以下方式绕过页面的 CSP: ```html ``` 注意到**之前的 CSP 仅允许执行内联脚本**。\ 然而,**只有 `if1` 和 `if2` 脚本将被执行,但只有 `if1` 能够访问父级秘密**。 ![](<../../images/image (372).png>) 因此,如果您可以将 JS 文件上传到服务器并通过 iframe 加载,即使 `script-src 'none'`,也有可能**绕过 CSP**。这也**可能通过滥用同站 JSONP 端点来实现**。 您可以通过以下场景进行测试,即使在 `script-src 'none'` 的情况下也会窃取 cookie。只需运行应用程序并使用浏览器访问它: ```python import flask from flask import Flask app = Flask(__name__) @app.route("/") def index(): resp = flask.Response('') resp.headers['Content-Security-Policy'] = "script-src 'self'" resp.headers['Set-Cookie'] = 'secret=THISISMYSECRET' return resp @app.route("/cookie_s.html") def cookie_s(): return "" if __name__ == "__main__": app.run() ``` #### 新的(2023-2025)CSP 绕过技术与 iframes 研究社区继续发现创造性的方法来利用 iframes 以击败限制性政策。以下是过去几年发布的最显著的技术: * **悬挂标记 / 命名 iframe 数据外泄 (PortSwigger 2023)** – 当一个应用程序反射 HTML 但强 CSP 阻止脚本执行时,您仍然可以通过注入一个 *悬挂* ` ``` ### Iframe sandbox iframe中的内容可以通过使用`sandbox`属性受到额外限制。默认情况下,此属性不被应用,这意味着没有限制。 当使用时,`sandbox`属性施加了几个限制: - 内容被视为来自一个独特的源。 - 任何提交表单的尝试都被阻止。 - 禁止执行脚本。 - 禁用对某些API的访问。 - 防止链接与其他浏览上下文交互。 - 不允许通过``、``、``或类似标签使用插件。 - 防止内容自身导航到其顶级浏览上下文。 - 自动触发的功能,如视频播放或表单控件的自动聚焦,被阻止。 提示:现代浏览器支持细粒度标志,如`allow-scripts`、`allow-same-origin`、`allow-top-navigation-by-user-activation`、`allow-downloads-without-user-activation`等。将它们组合以仅授予嵌入应用所需的最低能力。 属性的值可以留空(`sandbox=""`)以应用上述所有限制。或者,可以设置为一个以空格分隔的特定值列表,以使iframe免于某些限制。 ```html ``` ### Credentialless iframes 正如在 [this article](https://blog.slonser.info/posts/make-self-xss-great-again/) 中所解释的,iframe 中的 `credentialless` 标志用于在不发送凭据的请求的情况下加载页面,同时保持 iframe 中加载页面的同源策略 (SOP)。 自 **Chrome 110 (2023年2月) 起,该功能默认启用**,并且该规范正在以 *anonymous iframe* 的名称在各个浏览器中标准化。MDN 将其描述为:“一种机制,用于在全新的、短暂的存储分区中加载第三方 iframe,以便不与真实来源共享任何 cookies、localStorage 或 IndexedDB”。对攻击者和防御者的影响: * 不同的 credentialless iframes 中的脚本 **仍然共享相同的顶级来源**,并可以通过 DOM 自由交互,使多 iframe 自我 XSS 攻击成为可能(见下面的 PoC)。 * 由于网络是 **去凭据化的**,iframe 内的任何请求实际上表现为未认证会话 – CSRF 保护的端点通常会失败,但通过 DOM 泄露的公共页面仍在范围内。 * 从 credentialless iframe 生成的弹出窗口获得隐式的 `rel="noopener"`,破坏了一些 OAuth 流程。 ```javascript // PoC: two same-origin credentialless iframes stealing cookies set by a third window.top[1].document.cookie = 'foo=bar'; // write alert(window.top[2].document.cookie); // read -> foo=bar ``` - 利用示例:Self-XSS + CSRF 在此攻击中,攻击者准备了一个包含两个 iframe 的恶意网页: - 一个加载受害者页面的 iframe,带有 `credentialless` 标志,并且有一个触发 XSS 的 CSRF(想象一下用户的用户名中有 Self-XSS): ```html
``` - 另一个 iframe 实际上已经登录用户(没有 `credentialless` 标志)。 然后,从 XSS 中可以访问另一个 iframe,因为它们具有相同的 SOP,并通过执行来窃取 cookie: ```javascript alert(window.top[1].document.cookie); ``` ### fetchLater 攻击 正如[这篇文章](https://blog.slonser.info/posts/make-self-xss-great-again/)中所述,API `fetchLater` 允许配置请求在稍后执行(在一定时间后)。因此,这可以被滥用,例如,在攻击者的会话中登录受害者(使用 Self-XSS),设置一个 `fetchLater` 请求(例如更改当前用户的密码)并从攻击者的会话中注销。然后,受害者在自己的会话中登录,`fetchLater` 请求将被执行,将受害者的密码更改为攻击者设置的密码。 这样,即使受害者的 URL 不能在 iframe 中加载(由于 CSP 或其他限制),攻击者仍然可以在受害者的会话中执行请求。 ```javascript var req = new Request("/change_rights",{method:"POST",body:JSON.stringify({username:"victim", rights: "admin"}),credentials:"include"}) const minute = 60000 let arr = [minute, minute * 60, minute * 60 * 24, ...] for (let timeout of arr) fetchLater(req,{activateAfter: timeout}) ``` ## Iframes in SOP 检查以下页面: {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-1.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-2.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md {{#endref}} ## References * [PortSwigger Research – Using form hijacking to bypass CSP (March 2024)](https://portswigger.net/research/using-form-hijacking-to-bypass-csp) * [Chrome Developers – Iframe credentialless: Easily embed iframes in COEP environments (Feb 2023)](https://developer.chrome.com/blog/iframe-credentialless) {{#include ../../banners/hacktricks-training.md}}