利用表单劫持绕过CSP策略:实战分析与修复指南

本文详细介绍了如何通过表单劫持技术绕过内容安全策略(CSP),包括真实案例、漏洞原理、Burp Suite扫描检测方法及修复方案,帮助开发者强化Web应用安全防护。

利用表单劫持绕过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提交的漏洞报告:他利用Google脚本资源白名单注入AngularJS绕过CSP。修复后他又指出我们未防护表单劫持!虽无HTML注入漏洞,但此次CSP绕过促使我们强化安全,并奖励他1500美元。

原因分析

CSP 2.0规范中引入了form-action指令,但default-src不覆盖表单操作。忽略该指令会导致CSP易受表单劫持,Infosec Mastodon及本站均曾中招。本文旨在提高认知,帮助加固CSP策略。

CSP扫描检测

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

表单劫持

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

白名单资源

避免使用URL白名单(可能被脚本工具利用),建议使用安全随机nonce:

1
Content-Security-Policy: script-src 'nonce-RANDOM';

不可信脚本执行

避免使用'unsafe-inline'(易导致XSS),同时注意通配符域名、data:URL、unsafe-eval及弱nonce随机化。推荐nonce方案:

1
Content-Security-Policy: script-src 'nonce-RANDOM';

不可信样式执行

样式注入可能泄露敏感信息。检查'unsafe-inline'、通配符域名、data:URL及弱nonce,使用nonce修复:

1
Content-Security-Policy: style-src 'nonce-RANDOM';

语法错误

CSP会忽略畸形语法。扫描检查会报告不符合规范的指令或值。参考CSP规范修正语法。

点击劫持

检查X-Frame-Options和CSP的frame-ancestors指令。X-Frame-Options已弃用,推荐:

1
Content-Security-Policy: frame-ancestors 'none';

未强制CSP

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

常见错误

测试中发现开发者常犯以下错误:

协议错误

遗漏冒号:

1
Content-Security-Policy: script-src 'self' https   # 错误

应修正为:

1
Content-Security-Policy: script-src 'self' https:   # 正确

缺少分号

遗漏分号会导致指令名被误认为值:

1
frame-ancestors 'self' https://example.com default-src 'none'   # 错误

应修正为:

1
frame-ancestors 'self' https://example.com; default-src 'none'   # 正确

值错误

CSP中所有特殊值需引号包裹。常见未引号或非法值:

1
Content-Security-Policy: frame-ancestors DENY   # 错误(无DENY值)

应修正为:

1
Content-Security-Policy: frame-ancestors 'none'   # 正确

未引用的哈希或nonce

常见忘记为哈希/nonce加引号:

1
Content-Security-Policy: script-src sha512-BASE64HASH   # 错误

应修正为:

1
Content-Security-Policy: script-src 'sha512-BASE64HASH'   # 正确

Burp发布

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


相关研究

本文涉及技术标签:CSP、Burp Suite、表单劫持

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计