利用表单劫持绕过CSP:一种被忽视的安全威胁

本文详细介绍了如何通过表单劫持技术绕过内容安全策略(CSP),包括实际案例分析和Burp Suite中的被动扫描检查方法,帮助开发人员识别和修复常见的CSP配置错误,提升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。在我们修复之后,他还指出我们没有防范表单劫持!幸运的是,这仅仅是我们CSP的一个绕过,因为我们没有HTML注入漏洞,但收到这样能加强我们安全性的报告很好,所以我们给了他1500美元的赏金。

为什么会发生这种情况?

form-action指令在CSP第2版中指定。不幸的是,default-src不涵盖表单操作。这意味着如果您忽略此指令,您的CSP将容易受到表单劫持攻击,这正是Infosec Mastodon甚至我们自己网站发生的情况。因此,本文旨在提高对这个问题的认识,希望能加强许多CSP配置。

扫描您的CSP

我们最近在Burp中发布了一些新的CSP问题被动扫描检查。这些检查将发现诸如表单劫持、白名单资源、不受信任的脚本执行、不受信任的样式执行、格式错误语法、点击劫持和未强制执行的CSP等问题。我将逐一介绍,以便您在遇到这些问题时了解如何修复。

表单劫持

如果您的站点不使用表单操作(在现代应用中很常见),您可以使用’none’关键字指定指令,这是最安全的配置,因为攻击者将无法将表单发布到外部位置。如果您的站点需要"同站点"表单操作,则可以使用’self’关键字。最后,如果您想允许外部位置,可以指定URL,但请注意,如果攻击者发现HTML注入漏洞,他们也能向该位置发布数据。以下是每种配置的示例:

1
2
3
Content-Security-Policy: form-action 'none'
Content-Security-Policy: form-action 'self'
Content-Security-Policy: form-action https://portswigger.net

白名单资源

使用白名单URL是不良实践,因为它们可用于脚本小工具。此扫描检查将查看脚本指令,检查是否有任何域被加入白名单。要修复此问题,建议使用安全随机nonce来保护您的脚本:

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

不受信任的脚本执行

此问题指出当您在脚本指令中使用’unsafe-inline’时。顾名思义,这会为您的策略打开跨站脚本攻击的大门,因为您可以注入内联脚本标签。它还包括策略允许通配符域、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语法,并报告任何不符合规范的指令或值。我们对大量站点进行了扫描,发现了许多常见错误,此扫描检查将帮助消除这些错误。当发现某些无效语法时,指令或值将在问题详细信息中显示。要修复此问题,您应查阅CSP规范并确保语法正确。

点击劫持

此检查将检查CSP中的X-Frame-Options和frame-ancestors指令,并告知您的应用程序是否允许被框架。X-Frame-Options现已弃用,因此我们建议您使用frame-ancestors指令来缓解点击劫持攻击:

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

未强制执行的CSP

如果您的策略处于仅报告模式,Burp也会通知您,这意味着策略不会被强制执行但会记录结果。这通常用于过渡到强制策略,但经常会被错误地忽略。如果CSP不存在,它还会按站点报告问题,以鼓励开发人员部署一个。

实际应用

在测试Burp时,我们扫描了我们的漏洞赏金管道,发现了开发人员在部署CSP时犯的许多常见错误。我们将在下面重点介绍其中一些,以帮助您避免它们。

错误协议

一些网站在部署时经常忘记冒号:

1
Content-Security-Policy: script-src 'self' https

应该是:

1
Content-Security-Policy: script-src 'self' https:

您当然应该避免这样做,因为如果目标站点容易受到XSS攻击,攻击者将能够从任何具有TLS的域注入脚本资源。

缺少分号

忘记包含分号很常见。这可能导致指令名称被用作值,这意味着策略不会强制执行此指令!

这是不正确的:

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

frame-ancestors指令值中没有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。祝狩猎愉快!

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