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

时间:2009-06-02 21:29:06

标签: javascript html regex parsing code-injection

我正在保存用户提交的HTML(在数据库中)。我必须防止Javascript注入攻击。我见过的最有害的是style =“expression(...)”中的脚本。

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

Javascript攻击字符串的示例是:

1)

  

“你好,我有一个   <脚本>警报( “不好!”)< / SCRIPT>   < dog>的问题   元件...“

2)

  

“嗨,这个< b   风格= “宽度:表达式(警报( '坏!'))” >狗< / B个   是黑色的。“

有没有办法阻止这样的Javascript,并保持其余的完整?

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

修改 对不起,忘了提及环境 - 它本质上是MS堆栈:

  • SQL Server 2005
  • C#3.5(ASP.NET)
  • Javascript(显然)和jQuery。

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

编辑2:

感谢大家的链接。假设我可以定义我的列表(他的内容将包含许多数学和编程结构,因此白名单会非常烦人)我仍然有一个问题:

什么样的解析器可以让我删除“坏”部分?坏部分可能是一个完整的元素,但那么属于这些属性的脚本呢。我无法删除< a hrefs>无可奈何地

7 个答案:

答案 0 :(得分:35)

你认为那是吗? Check this out

无论采取何种方法,您都需要使用白名单。这是唯一可以接近您在网站上允许的内容的方法。

修改

遗憾的是,我不熟悉.NET,但您可以查看stackoverflow自己与XSS(http://blog.stackoverflow.com/2008/06/safe-html-and-xss/)之间的争斗以及为解析此站点上发布的HTML而编写的代码:Archive.org link - 显然你可能需要改变它,因为你的白名单更大,但这应该让你开始。

答案 1 :(得分:6)

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

任何更少的东西,你正在打开自己的问题 - 已知的漏洞或将来会发现的漏洞。

答案 2 :(得分:4)

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

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

答案 3 :(得分:2)

基本上,正如Paolo所说,你应该专注于允许用户做什么,而不是试图过滤掉他们不应该做的事情。

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

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

答案 4 :(得分:1)

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

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

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

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

答案 5 :(得分:0)

您使用的服务器端代码是什么?根据哪些或多种方式可以过滤掉恶意脚本,但这是危险的区域。即使是经验丰富的专业人士也会被抓获:http://www.codinghorror.com/blog/archives/001167.html

答案 6 :(得分:-2)

您可以使用此限制功能。

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 , "" );
}