如何防止用户生成的 HTML 中的 Javascript 注入攻击

Posted

技术标签:

【中文标题】如何防止用户生成的 HTML 中的 Javascript 注入攻击【英文标题】:How to prevent Javascript injection attacks within user-generated HTML 【发布时间】:2010-10-30 19:57:44 【问题描述】:

我正在保存用户提交的 html(在数据库中)。我必须防止 javascript 注入攻击。我见过的最有害的是 style="expression(...)" 中的 JavaScript。

除此之外,相当多的有效用户内容将包括特殊字符和 XML 结构,因此我希望尽可能避免使用白名单方法。 (列出每个允许的 HTML 元素和属性)。

JavaScript 攻击字符串示例:

1.

"Hello, I have a
<script>alert("bad!")</script>
problem with the <dog>
element..."
"Hi, this <b
style="width:expression(alert('bad!'))">dog</b>
is black."

有没有办法阻止此类 JavaScript,并保持其余部分完好无损?

到目前为止,我唯一的解决方案是使用正则表达式来删除某些模式。它解决了案例 1,但没有解决案例 2。

环境本质上是 Microsoft 堆栈:

SQL Server 2005 C# 3.5 (ASP.NET) JavaScript 和 jQuery。

我希望阻塞点是 ASP.NET 层 - 任何人都可以制作错误的 HTTP 请求。

编辑

谢谢大家的链接。假设我可以定义我的列表(内容将包括许多数学和编程结构,所以白名单会很烦人),我还有一个问题:

什么样的解析器可以让我只删除“坏”部分?坏的部分可能是整个元素,但是那些驻留在属性中的脚本呢?我无法删除< a hrefs >willy-nilly。

【问题讨论】:

【参考方案1】:

目前最好的选择是使用 Content Security Policy 标头,如下所示:

Content-Security-Policy: default-src 'self';

这将阻止加载内联和外部脚本、样式、图像等,因此浏览器只会加载和执行来自同一来源的资源。

但是,它不适用于旧浏览器。

【讨论】:

这会阻止我们使用 CDN 吗? @DanielWu 是的,但是您可以将 CDN 域或文件哈希列入白名单【参考方案2】: 在我看来,

元素和属性的白名单是唯一可接受的选择。任何不在您的白名单上的内容都应该被删除或编码(将 &" 更改为实体)。另外请务必检查您允许的属性内的值。

再少一点,您就会面临问题——已知的漏洞利用或将来会发现的漏洞。

【讨论】:

【参考方案3】:

您可以使用此限制功能。

function restrict(elem)
  var tf = _(elem);
  var rx = new RegExp;
  if(elem == "email")
       rx = /[ '"]/gi;
  else if(elem == "search" || elem == "comment")
    rx = /[^a-z 0-9.,?]/gi;
  else
      rx =  /[^a-z0-9]/gi;
  
  tf.value = tf.value.replace(rx , "" );

【讨论】:

没有任何解释就转储代码只会引起混乱,尤其是如果它甚至不起作用:这是什么意思 --> _(elem) ?【参考方案4】:

你认为是这样吗? Check this out.

无论您采取何种方法,您都绝对需要使用白名单。这是确保您在网站上允许的内容安全的唯一方法。

编辑

不幸的是,我不熟悉 .NET,但您可以查看 *** 自己与 XSS 的战斗 (https://blog.***.com/2008/06/safe-html-and-xss/) 以及本网站上发布的用于解析 HTML 的代码:Archive.org link - 显然您可能需要更改此设置,因为您的白名单更大,但这应该可以帮助您入门。

【讨论】:

谢谢,我实际上将该站点用作测试平台。我已经成功删除了任何看起来像 的东西,所以我需要得到那些不...即表达式:,javascript:,vbscript:等。你能建议一个可以做到这一点的解析器吗? 如果你的方法是删除危险的东西,你的代码很容易被注入。唯一安全的方法是拥有一个明确允许的元素和属性的白名单。 感谢您的反馈。我担心白名单就是答案。 :) 杰夫,试试这个字符串:<scr<script>ipt>。耶 XSS!黑名单将不起作用。无论您的白名单是否长,都无法将其列入黑名单。如果您想阅读更多关于此的文章,OWASP 网站可以提供很大帮助。 想在这里解释一下什么是白名单以及它是如何运作/删除坏东西的?【参考方案5】:

唯一真正安全的方法是使用白名单。对所有内容进行编码,然后将允许的代码转换回来。

我已经看到了只禁止危险代码的相当高级的尝试,但它仍然无法正常工作。尝试安全地捕获任何人能想到的所有东西是相当了不起的壮举,而且它很容易对一些根本不危险的东西进行烦人的替换。

【讨论】:

我发现很难。我们现在正在使用转义和白名单。【参考方案6】:

基本上,正如 Paolo 所说,您应该尝试关注用户被允许做的事情,而不是试图过滤掉他们不应该做的事情。

保留允许的 HTML 标记列表(例如 b、i、u...)并过滤掉其他所有标记。您可能还想删除允许的 HTML 标记的所有属性(例如,因为您的第二个示例)。

另一个解决方案是引入所谓的 BB 代码,这是很多论坛使用的。它具有与 HTML 相似的语法,但从允许代码白名单的想法开始,然后将其转换为 HTML。例如,[b]example[/b] 将导致 example。确保在使用 BB 代码时仍然预先过滤掉 HTML 标签。

【讨论】:

我担心的内容将包括许多数学和编程结构(XML、C# 等),所以我希望避免列入白名单。【参考方案7】:

您使用的是什么服务器端代码?取决于您可以过滤掉恶意脚本的数量或方法,但这是危险的领域。即使是经验丰富的专业人士也会被抓住:http://www.codinghorror.com/blog/archives/001167.html

【讨论】:

以上是关于如何防止用户生成的 HTML 中的 Javascript 注入攻击的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中防止页面刷新

如何在生成的 HTML 页面中隐藏 JavaScript 注释? [关闭]

如何专门防止或锁定列表控件中的行选择(报表视图)

生成注册激活密钥时如何防止冲突?

如何从 HTML 文件在 ASPX 文件中运行 javascript 函数?

使用 jQuery 防止 html 输入中的值