利用表单劫持绕过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日)