postMessage 风险在哪
postMessage 是跨窗口通信机制,发送侧用 targetOrigin 指定接收方来源,接收侧需要在消息事件中校验来源与数据结构。常见问题是发送侧写成通配来源、接收侧完全不校验来源或只做简单字符串包含判断。因为消息可以来自任意窗口(包括被注入的第三方页面),接收侧的校验才是真正的防线。
基本信息
| 适用平台 | 浏览器前端(JavaScript),常见于 iframe 嵌入与多标签通信 |
|---|---|
| 检查方式 | 代码审计为主,配合自有页面的动态验证 |
| 发送侧要点 | targetOrigin 使用精确来源,避免通配 |
| 接收侧要点 | 校验 event.origin 白名单与 event.data 结构与类型 |
典型使用场景
- 主站与嵌入 iframe(支付、客服、地图)之间的通信审计
- 单点登录回跳与跨域身份传递场景的安全评审
- 微前端架构中子应用间的消息传递核查
- 第三方组件 SDK 的使用风险盘点
- 评估“接收侧敏感操作能否被外部页面触发”
审计要点
审计要点
发送侧:排查 postMessage(..., '*') 与拼接字符串构造的来源
接收侧:addEventListener('message') 回调是否校验 event.origin 是否在白名单内
结构校验:是否验证 event.data 的类型与必需字段,避免把任意数据当指令处理
敏感动作:消息触发的动作是否包含跳转、登录态变更、数据请求
嵌入场景:主站与 iframe、子应用之间的双向通信都要覆盖检查点与判据
| 检查点 | 安全实现 | 风险实现 |
|---|---|---|
| 发送来源 | 精确指定目标来源 | 使用通配来源 |
| 来源校验 | 白名单精确匹配 | 不校验或用包含判断 |
| 数据校验 | 校验类型与必需字段 | 直接按字段执行动作 |
| 动作范围 | 仅限无害展示与查询 | 可触发状态变更或跳转 |
| 调试代码 | 生产环境已移除 | 遗留通配来源的消息发送 |
来源白名单判断要精确比较,避免使用简单的字符串包含判断:形如 example.com.attacker.net 的来源可以绕过包含式判断。
动态验证时使用自建页面作为发送方来控制变量:这是确认接收侧是否校验来源的最直接方式,也不会影响第三方页面。