当前防止持续 XSS 攻击的最佳实践

信息安全 xss
2021-09-03 15:32:34

我有一个文本字段,允许用户输入他/她想要的任何内容。保存后,结果稍后会在屏幕上显示给潜在的许多人。

XSS 对我来说似乎有点像黑魔法,所以我想知道当前处理这种情况的最佳实践是什么(从清理输入的特定方法到编码 html 以显示的特定方法)?

4个回答

由于您想要当前的最佳实践,而这里的最新答案是 2012 年 8 月,我想我不妨权衡一下并更新它。

防止任何类型的 XSS 攻击(持久、反射、DOM 等)的最佳实践。

  1. 严格验证所有输入。例如,如果您要求提供英国邮政编码,请确保只允许使用字母、数字和空格字符。在服务器端执行此操作,如果验证失败,向用户显示一条消息,以便他们更正输入。对您无法控制的所有变量执行此操作,包括查询字符串、POST 数据、标题和 cookie。
  2. 为自己添加一些安全标头
  • X-XSS-Protection: 1; mode=block将反射型 XSS 浏览器保护激活为阻止模式而不是过滤模式。阻止模式阻止这样的攻击。编辑 2021-01-28:此标头现已弃用,因为 Chrome 等浏览器不再包含 XSS 审核员。
  • X-Content-Type-Options: nosniff 防止将 JavaScript 插入图像和其他内容类型。
  • Content-Security-Policy:至少有严格的script-srcstyle-src不允许unsafe-inlineunsafe-eval这是杀死 XSS 的标头之父。
  1. 输出遵循OWASP XSS(跨站点脚本)预防备忘单 中的规则,但是对于规则 #3,我将改为执行以下操作:
  • 使用 HTML数据属性在页面上输出任何动态内容。
  • 例如<body data-foo="@foo" />
  • Where@foo将输出变量的 HTML 编码版本。例如" />会给<body data-foo="&quot; &#x2F;&gt;" />
  • 使用 JQuery 或 JavaScript 获取这些值:var foo = $("body").data("foo");
  • 这样你就不必担心任何双重编码,除非你的 JavaScript 稍后插入为 HTML,但是当你在那里处理编码而不是将它们混合在一起时,事情仍然更简单。
  • 如果您正在使用,请使用如下函数进行 HTML 编码document.write,否则您可能会引入漏洞。理想情况下,虽然使用textContent或 JQuery 的text()attr()功能。

以相反的顺序处理这些问题。专注于#3,因为这是 XSS 的主要缓解措施,#2 告诉浏览器不要执行任何漏掉的东西,#1 是一个很好的纵深防御措施(如果特殊字符无法进入,它们可以)不要出去)。但是,#1 较弱,因为并非所有字段都可以严格验证,并且可能会损害功能(想象 Stack Exchange 无法允许“ <script>”作为输入)。


function escapeHtml(str) {
    return String(str)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#039;")
        .replace(/\//g, "&#x2F;")
}

转义引号,过滤掉javascript这个词,限制允许的字母等。

您可能只想通读有关 XSS 的 OWASP 指南

OWASP 的这个附加页面应该很有用,它处理了我们下面讨论中的编码问题。

使用自动转义模板语言编写 HTML,默认情况下,该语言会为您转义不受信任的输入。

例如,Django 模板转义 HTML 特殊字符

显然,不应盲目信任用户提交的数据并将其直接插入到您的网页中,因为恶意用户可能会利用这种漏洞来做潜在的坏事。这种类型的安全漏洞称为跨站点脚本 (XSS) 攻击。

为避免此问题,您有两种选择:

  1. 您可以确保通过转义过滤器运行每个不受信任的变量,这会将可能有害的 HTML 字符转换为无害的字符。这是 Django 最初几年的默认解决方案,但问题是它让您(开发人员/模板作者)有责任确保您逃避一切。很容易忘记转义数据。
  2. 您可以利用 Django 的自动 HTML 转义。本节的其余部分描述了自动转义的工作原理。默认情况下,在 Django 中,每个模板都会自动转义每个变量标签的输出。

还有各种更智能的上下文自动转义模板,即使您的模板包含嵌入的 JavaScript、CSS 和 URL,也可以防止 XSS。

闭包模板说:

上下文自动转义通过增加闭包模板来根据其出现的上下文正确编码每个动态值,从而防御攻击者控制的值中的 XSS 漏洞。

Go 的模板语言使用上下文自动转义:

HTML 模板将数据值视为应编码的纯文本,以便它们可以安全地嵌入到 HTML 文档中。转义是上下文相关的,因此动作可以出现在 JavaScript、CSS 和 URI 上下文中。

单一的最佳实践:严格控制类型并清理您的数据。

始终使用正确的方法根据类型输出数据:永远不要将输入的内容渲染为 HTML 中的文本(即将用户输入的文本数据分配给.dataDOM 中的文本节点属性,而不是魔法.innerHTML)。永远不要在 -like 构造中使用输入eval或作为数据库查询的子字符串 - 适当的工具将分别是表达式解析器和占位符。

拒绝或清理从外部来源(包括您自己的内部数据库,也可能受到损害!)到严格的允许模式集的所有内容。

使用已建立且经过验证的协议和序列化程序来传输数据,最好是在发送端和接收端都有本地实现(JSON 序列化程序、protobuf、Perl 中的可存储等),而不是自制的引用。