利用表单劫持绕过CSP策略:实战技术与防护指南

本文详细解析如何通过表单劫持技术绕过内容安全策略(CSP),包括实际案例、CSP配置漏洞分析、Burp Suite扫描检测方法,以及修复方案。涵盖form-action指令缺陷、密码管理器风险、CSP语法常见错误及防护实践。

利用表单劫持绕过CSP | PortSwigger研究

Gareth Heyes
研究员
@garethheyes

发布时间:2024年3月5日 14:55 UTC
更新时间:2024年3月5日 14:55 UTC


本文将展示如何通过一种常被忽视的技术绕过内容安全策略(CSP),在看似安全的配置中实现密码窃取。

什么是表单劫持?

表单劫持并非广为人知的技术:其核心思路是,当存在受CSP保护的HTML注入漏洞时,攻击者利用formaction属性或注入自定义表单,将数据发送到攻击者服务器。过度积极的密码管理器还会自动填充注入的输入字段凭证,使得攻击危害性显著。

实际案例

我们在Infosec Mastodon上发现了一个真实案例:其使用的Mastodon分支未正确过滤HTML。攻击者可在Chrome密码管理器自动填充凭证后,通过表单劫持将凭证发送至自己的服务器。最终用户会在Infosec Mastodon上看到帖子,点击看似界面组件的元素,实则将凭证发送给攻击者。

一年后,我们收到Johan Carlsson提交的优秀漏洞报告:他通过注入AngularJS利用Google脚本资源白名单绕过CSP。修复后他又指出我们未防护表单劫持!尽管这只是CSP绕过(无HTML注入漏洞),但报告强化了安全性,因此我们授予他1,500美元奖金。

原因分析

CSP第2版定义了form-action指令,但default-src不覆盖表单操作。若忽略此指令,CSP将易受表单劫持,Infosec Mastodon甚至本网站都曾中招。本文旨在提高对此问题的认知,助力强化CSP部署。

CSP扫描实践

Burp新增被动扫描检查功能,可检测表单劫持、白名单资源、不可信脚本/样式执行、语法错误、点击劫持和未强制CSP等问题。以下逐项说明修复方案:

表单劫持

  • 若站点无需表单操作(现代应用常见),可使用'none'关键字:
    Content-Security-Policy: form-action 'none'
  • 若需同站表单操作,使用'self'
    Content-Security-Policy: form-action 'self'
  • 若需允许外部URL,需注意攻击者可能利用HTML注入向其发送数据:
    Content-Security-Policy: form-action https://portswigger.net

白名单资源

使用白名单URL易被利用为脚本工具,建议改用安全随机nonce:
Content-Security-Policy: script-src 'nonce-RANDOM';

不可信脚本执行

使用'unsafe-inline'会开放跨站脚本攻击风险,同时涵盖通配符域名、data: URL、unsafe-eval和弱随机nonce。解决方案:
Content-Security-Policy: script-src 'nonce-RANDOM';

不可信样式执行

样式注入可能泄露页面敏感信息。若使用'unsafe-inline'或通配符/data: URL/弱nonce,需修复:
Content-Security-Policy: style-src 'nonce-RANDOM';

语法错误

CSP遇到错误语法会忽略值或指令。扫描检查会报告不符合规范的指令/值,需参考CSP规范修正。

点击劫持

检查X-Frame-Options和CSP的frame-ancestors指令。X-Frame-Options已弃用,推荐使用:
Content-Security-Policy: frame-ancestors 'none';

未强制CSP

Burp会报告策略是否处于仅记录模式(未强制执行),并鼓励未部署CSP的站点启用。

常见错误实例

测试Burp时扫描漏洞赏金管道,发现开发者常犯以下错误:

协议错误

遗漏冒号:
Content-Security-Policy: script-src 'self' https
应修正为:
Content-Security-Policy: script-src 'self' https:

缺少分号

遗漏分号会导致指令名被误认为值:
错误示例:
frame-ancestors 'self' https://example.com default-src 'none'
正确示例:
frame-ancestors 'self' https://example.com; default-src 'none'

值错误

CSP中所有特殊值需加引号。常见未引号或非法值:
错误示例:
Content-Security-Policy: frame-ancestors DENY
正确示例:
Content-Security-Policy: frame-ancestors 'none'

未引用的哈希或nonce

许多站点忘记为哈希/nonce加引号:
错误示例:
Content-Security-Policy: script-src sha512-BASE64HASH
正确示例:
Content-Security-Policy: script-src 'sha512-BASE64HASH'

Burp发布

希望通过本文提高对表单劫持和CSP常见错误的认知。如需扫描站点,可通过早期采用渠道获取Burp。祝狩猎愉快!


相关研究

  • Document My Pentest: you hack, the AI writes it up! (2025年4月23日)
  • Shadow Repeater: AI-enhanced manual testing (2025年2月20日)
  • Bypassing CSP via DOM clobbering (2023年6月5日)
  • Ambushed by AngularJS: a hidden CSP bypass in Piwik PRO (2023年4月28日)
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计