什么是跨站脚本?如何防范 XSS 攻击

2021-08-24 15:46:28 浏览数 (4768)

跨站脚本是应用程序安全开源基金会 (OWASP) 前 10 名中第二个最普遍的问题——它存在于大约 2/3 的所有应用程序中。虽然自动化工具可以发现其中的一些问题,但也有一些旨在检测和利用这些漏洞的自动化工具。

什么是跨站脚本?

当数据通过不受信任的来源(如 Web 请求)进入 Web 应用程序并未经验证就发送给用户时,就会发生 XSS 攻击。

XSS 会导致脚本在用户的浏览器中执行,从而导致会话被劫持、网站篡改以及将用户重定向到恶意站点。

从本质上讲,攻击者将恶意代码输入到用户输入的部分中,服务器希望该部分是数据(但实际上是为了执行而设计的代码)。

如果处理不当,恶意代码可能会突破“数据平面”并作为正常代码(“控制平面”)执行。

我们可以将大多数 XSS 攻击分为两类:存储的和反射的。第三种不太常见,称为基于 DOM 的 XSS。

当数据通过不受信任的来源进入并发送给用户(在动态内容中)而没有检查恶意内容时,就会发生任何 XSS 攻击。恶意内容可以是 JavaScript、Flash、HTML 或浏览器能够执行的任何其他代码。

反射型 XSS(影响:中等)

这是最基本的 XSS 类型,其中应用程序接收数据,然后以不安全的方式将这些数据包含在对用户的响应中。

例如,如果攻击者说服用户单击此网络钓鱼链接:

http://legitwebsite.com/message=<script>恶意代码</script>

如果合法站点不处理数据而只是将其返回给用户,则用户的浏览器将执行恶意代码。

存储型 XSS(影响:严重)

当注入永久存储在目标的服务器上时,就会发生存储型 XSS,例如论坛或评论部分、数据库中的消息等。从本质上讲,这意味着该漏洞会影响站点/应用程序的每个访问者。

例如,如果站点允许用户发表评论,然后显示他们的评论,则用户可以输入以下内容:

<p><script>恶意代码</script></p>

如果站点没有适当地检查用户输入,则可能会导致脚本为看到此消息的任何其他用户执行。

基于DOM的XSS/客户端XSS(影响:中等)

反射型 XSS 和存储型 XSS 与基于 DOM 的最大区别在于攻击的注入位置。

反射和存储 XSS 是服务器端问题,而基于 DOM 是客户端(浏览器)端问题。基于 DOM 的 XSS 发生在 DOM(文档对象模型)中,而不是作为 HTML 的一部分。

这种攻击不是在页面中插入恶意代码,而是允许加载合法页面,然后利用用户输入向页面添加 HTML,执行恶意脚本。这利用了客户端生成的 HTML 数量不断增加的优势。

例如,攻击者可以通过社会工程使受害者点击恶意链接(例如 http://www.legitimatewebsite.com/contact#<script>malicious code</script>)。该网站将收到对该页面的合法请求,但不会收到恶意片段(因为浏览器不会向站点的服务器发送 # 字符后的任何内容)。受害者会看到合法网站,但受害者的浏览器也会执行恶意脚本。

由于这种攻击的工作方式,服务器端保护不会阻止它,因为恶意代码根本没有发送到服务器。

相反,防止这种攻击需要确保 JavaScript 不会以不安全的方式解释 URI 片段(统一资源标识符 - URI 标识指定位置的资源,例如 URL)。

XSS 攻击的缓解措施

有效缓解 XSS 攻击需要结合以下措施,当您将它们结合使用时,可以提供强大的 XSS 防御。

避免在指定位置以外的任何地方插入用户提供的/不受信任的数据

这是第一个也是最重要的规则。编码、转义、验证和过滤输入极其困难且非常复杂。

限制某人可以输入不可信数据的位置要容易得多。最安全的假设是所有不受信任的数据都是恶意的。

验证/过滤输入

理想情况下,所有输入都应根据可接受的值列表进行验证。

编码输出

任何用户输入的数据都应该被编码以防止它被读取为活动的。这可能需要 CSS、JavaScript、URL 和/或 HTML 编码。

确保输出在任何暴露的点都被编码尤为重要,因为相同的数据可以存储并显示在多个位置。

谨慎选择框架

使用提供自动转义功能的框架(如 Go 模板)或具有针对 XSS 的本机防御(如 .NET 的请求验证)的框架。

设置 HttpOnly 标志

XSS 攻击通常使用 JavaScript 来窃取会话 cookie(而普通的 Web 应用程序很少需要使用 JavaScript 来访问会话 cookie)。因此,设置 HttpOnly 标志可以保护会话 cookie 免受攻击者的攻击,同时不会限制正常行为。大多数浏览器都支持设置这个标志。

使用响应头

与 HttpOnly 标志类似,任何不应包含 HTML 或 JavaScript 的 HTTP 响应都可以利用“Content-Type”和“X-Content-Type-Options”标头来确保浏览器仅以预期的方式解释响应。

对开发人员进行安全教育

专门针对开发人员的教育,例如将应用程序安全团队成员与开发人员配对的“安全冠军”计划,很重要。它们可以帮助开发人员了解安全漏洞(如 XSS)以及如何防止它们。

制定内容安全政策

内容安全策略 (CSP) 可以帮助您检测和缓解 XSS 和其他数据注入攻击。

他们为受信任内容的来源设置了许可名单,并且只能应用于敏感页面(如支付页面),或者理想情况下,应用于整个网站。如果内容是从不应加载的页面加载的,他们甚至可以提供通知。

它们相当容易部署 - 只需将 Content-Security-Policy HTTP 标头添加到网页和任何适当的指令即可。

CSP提琴手扩展可以帮助您生成一个基准CSP。该工具将围绕浏览器提交的报告构建策略,创建可更改的基线策略。

此外,您可以使用由 Troy Hunt 和 Scott Helme 运行的Report URI来获取有关 CSP 违规的警报,以便更主动地监控您的站点。

通常,策略由一系列指令组成,这些指令将描述一种资源或区域的策略。这些指令之一,子资源完整性检查,用于确保浏览器验证第三方内容(来自 CDN 之类的来源)是在没有被操纵的情况下交付的。

本质上,提供的加密哈希必须与加载的文件匹配。如果黑客修改了第三方的内容,该站点将不会加载恶意内容。

问题是,如果内容提供者更新文件或进行合法更改,内容也不会加载(因为哈希值已更改)。

解决此问题的主要方法是利用版本化的 JavaScript 资源,例如 chatbot_0.1.23.js,而不是 chatbot.js。这是一般的最佳实践,也保证了JS文件发生变化时服务的连续性。

虽然浏览器并不普遍支持此功能,但对于那些缺少该功能的浏览器,使用它不会破坏站点(它只是不会利用该技术)。

有关各种指令的更多详细信息,请查看这些 指南