6

下面的代码无法捕捉到的危险示例是什么?

编辑:在一些评论之后,我添加了另一行,评论如下。请参阅 Vinko 在 David Grant 的回答中的评论。到目前为止,只有 Vinko 回答了这个问题,该问题要求提供可以忽略此功能的具体示例。Vinko 提供了一个,但我已经编辑了代码来关闭这个漏洞。如果你们中的其他人能想到另一个具体的例子,你会得到我的投票!

public static string strip_dangerous_tags(string text_with_tags)
{
    string s = Regex.Replace(text_with_tags, @"<script", "<scrSAFEipt", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"</script", "</scrSAFEipt", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"<object", "</objSAFEct", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"</object", "</obSAFEct", RegexOptions.IgnoreCase);
    // ADDED AFTER THIS QUESTION WAS POSTED
    s = Regex.Replace(s, @"javascript", "javaSAFEscript", RegexOptions.IgnoreCase);

    s = Regex.Replace(s, @"onabort", "onSAFEabort", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onblur", "onSAFEblur", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onchange", "onSAFEchange", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onclick", "onSAFEclick", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"ondblclick", "onSAFEdblclick", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onerror", "onSAFEerror", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onfocus", "onSAFEfocus", RegexOptions.IgnoreCase);

    s = Regex.Replace(s, @"onkeydown", "onSAFEkeydown", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onkeypress", "onSAFEkeypress", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onkeyup", "onSAFEkeyup", RegexOptions.IgnoreCase);

    s = Regex.Replace(s, @"onload", "onSAFEload", RegexOptions.IgnoreCase);

    s = Regex.Replace(s, @"onmousedown", "onSAFEmousedown", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onmousemove", "onSAFEmousemove", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onmouseout", "onSAFEmouseout", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onmouseup", "onSAFEmouseup", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onmouseup", "onSAFEmouseup", RegexOptions.IgnoreCase);

    s = Regex.Replace(s, @"onreset", "onSAFEresetK", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onresize", "onSAFEresize", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onselect", "onSAFEselect", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onsubmit", "onSAFEsubmit", RegexOptions.IgnoreCase);
    s = Regex.Replace(s, @"onunload", "onSAFEunload", RegexOptions.IgnoreCase);

    return s;
}
4

11 回答 11

48

永远不够——白名单,不要黑名单

例如,javascript:伪 URL 可能会被 HTML 实体混淆,您已经忘记了,并且在 IE 中<embed>存在危险的 CSS 属性,例如behavior和。expression

逃避过滤的方法有无数种,这种方法注定会失败。即使您今天发现并阻止了所有可能的漏洞利用,未来也可能会添加新的不安全元素和属性。

只有两种保护 HTML 的好方法:

  • <通过将 every替换为.将其转换为文本&lt;
    如果您想允许用户输入格式化文本,您可以使用自己的标记(例如,像 SO 那样的降价)。

  • 将 HTML 解析为 DOM,检查每个元素和属性并删除所有未列入白名单的内容。
    您还需要检查允许属性的内容,例如href(确保 URL 使用安全协议,阻止所有未知协议)。
    清理 DOM 后,从中生成新的有效 HTML。永远不要像处理文本一样处理 HTML,因为无效的标记、评论、实体等很容易欺骗您的过滤器。

还要确保您的页面声明其编码,因为存在利用浏览器自动检测错误编码的漏洞。

于 2008-10-12T17:04:36.637 回答
10

你最好把所有都<变成&lt;和全部>变成&gt;,然后将可接受的标签转换回来。换句话说,白名单,不要黑名单。

于 2008-10-12T16:40:19.493 回答
7

正如大卫所展示的那样,仅使用一些正则表达式来保护您并没有简单的方法,您总是可以忘记一些东西,例如 javascript: 在您的情况下。您最好在输出时转义 HTML 实体。有很多关于执行此操作的最佳方法的讨论,具体取决于您实际需要允许的内容,但可以肯定的是您的功能还不够

Jeff 在这里谈了一点。

于 2008-10-12T16:35:00.673 回答
4
<a href="javascript:document.writeln('on' + 'unload' + ' and more malicious stuff here...');">example</a>

每当您可以在文档中写入字符串时,都会打开一扇大门。

有无数地方可以将恶意内容注入 HTML/JavaScript。出于这个原因,Facebook 最初不允许在他们的应用程序平台中使用 JavaScript。他们的解决方案是稍后实现一个标记/脚本编译器,允许他们认真过滤掉坏东西。

如前所述,将一些标签和属性列入白名单,并去掉其他所有内容。不要将一些已知的恶意属性列入黑名单并允许其他所有内容。

于 2008-10-12T16:27:56.273 回答
3

虽然我不能提供一个具体的例子来说明为什么不这样做,但我会继续直截了当地说不。这更多的是原则。正则表达式是一个了不起的工具,但它们只能用于某些问题。它们非常适合数据匹配和搜索。

然而,它们并不是一个很好的安全工具。弄乱正则表达式并使其仅部分正确太容易了。黑客可以在结构不佳甚至结构良好的正则表达式中找到很多回旋余地。我会尝试另一种方法来防止跨站点脚本。

于 2008-10-12T16:37:32.243 回答
3

查看http://ha.ckers.org/xss.html上的 XSS 备忘单,这不是一个完整的列表,而是一个好的开始。

想到的一个是 <img src="http://badsite.com/javascriptfile" />

您还忘记了 onmouseover 和样式标签。

最简单的事情就是实体转义。如果向量一开始就无法正确渲染,那么不完整的黑名单就无关紧要了。

于 2008-10-13T15:55:27.943 回答
3

作为通过此攻击的示例:

  <div style="color: expression('alert(4)')">

无耻插件:Caja 项目定义了 HTML 元素和属性的白名单,以便它可以控制 HTML 中的脚本如何以及何时执行。

请参阅http://code.google.com/p/google-caja/上的项目,白名单是http://code.google.com/p/google-caja/source/browse/#svn 中的 JSON 文件 /trunk/src/com/google/caja/lang/htmlhttp://code.google.com/p/google-caja/source/browse/#svn/trunk/src/com/google/caja/lang/ css

于 2009-01-09T23:32:14.777 回答
3

我仍然没有弄清楚为什么开发人员想要通过正则表达式替换将错误的输入转化为好的输入。除非您的网站是博客并且需要允许嵌入 html 或 javascript 或任何其他类型的代码,否则请拒绝错误输入并返回错误。俗话说垃圾进垃圾出,你为什么要吸收一大堆热气腾腾的便便,让它可以食用呢?

如果您的网站没有国际化,为什么要接受任何 unicode?

如果您的网站只做 POST,为什么要接受任何 URL 编码的值?

为什么接受任何十六进制?为什么接受 html 实体?什么用户输入' '或'"' ?

至于正则表达式,可以使用它们,但是,您不必为完整的攻击字符串编写单独的正则表达式。只需几个构造良好的正则表达式模式,您就可以拒绝许多不同的攻击签名:

patterns.put("xssAttack1", Pattern.compile("<script",Pattern.CASE_INSENSITIVE) );
patterns.put("xssAttack2", Pattern.compile("SRC=",Pattern.CASE_INSENSITIVE) );
patterns.put("xssAttack3", Pattern.compile("pt:al",Pattern.CASE_INSENSITIVE) );
patterns.put("xssAttack4", Pattern.compile("xss",Pattern.CASE_INSENSITIVE) );

<FRAMESET><FRAME SRC="javascript:alert('XSS');"></FRAMESET>
<DIV STYLE="width: expression(alert('XSS'));">
<LINK REL="stylesheet" HREF="javascript:alert('XSS');">
<IMG SRC="jav   ascript:alert('XSS');">    // hmtl allows embedded tabs...
<IMG SRC="jav&#x0A;ascript:alert('XSS');"> // hmtl allows embedded newline...
<IMG SRC="jav&#x0D;ascript:alert('XSS');"> // hmtl allows embedded carriage return...

请注意,我的模式不是完整的攻击签名,仅足以检测该值是否是恶意的。用户不太可能输入 'SRC=' 或 'pt:al' 这允许我的正则表达式模式检测包含任何这些令牌的未知攻击。

许多开发人员会告诉您,您无法使用黑名单保护网站。由于攻击集是无限的,这基本上是正确的,但是,如果您使用基于令牌构建的黑名单解析整个请求(参数、参数值、标头、cookie),您将能够弄清楚什么是攻击什么是有效的。请记住,攻击者很可能会通过工具对您进行霰弹枪攻击。如果你已经适当地强化了你的服务器,他将不知道你正在运行什么环境,并且必须用漏洞列表来爆破你。如果他足够缠扰你,请将攻击者或他的 IP 放在隔离列表中。如果他有一个带有 50k 漏洞的工具可以攻击你的网站,如果每次违规将他的id或ip隔离30分钟,他需要多长时间?诚然,如果攻击者使用僵尸网络进行多路攻击,仍然存在风险。您的网站最终仍然是一个更难破解的金块。

现在已经检查了恶意内容的整个请求,您现在可以使用白名单类型检查对长度、引用/逻辑、命名来确定请求的有效性

不要忘记实施某种 CSRF 保护。也许是一个蜂蜜令牌,并检查先前请求中的用户代理字符串以查看它是否已更改。

于 2012-08-03T18:02:54.893 回答
2

空白让你变得脆弱。读这个

于 2008-10-12T17:11:28.963 回答
1

对白名单的另一次投票。但看起来你正在以错误的方式解决这个问题。这样做的方式是将 HTML 解析为标签树。如果你正在解析的标签在白名单中,给它一个树节点,然后解析。它的属性也是如此。

丢弃的属性只是被丢弃。其他一切都是 HTML 转义的文字内容。

这条路线的好处是因为您有效地重新生成了所有标记,这都是完全有效的标记!(当人们留下评论并且他们搞砸了验证/设计时,我讨厌它。)

关于“我不能列入白名单”(段落):黑名单是一种需要大量维护的方法。您必须密切关注新的漏洞并确保您的安全。是个可怜的存在。只要做对一次,你就再也不需要碰它了。

于 2008-10-12T16:53:22.947 回答
1

从不同的角度来看,当有人想要在他们提交的内容中添加“javascript”或“functionload”或“visionblurred”时会发生什么?由于多种原因,这可能在大多数地方发生……据我了解,这些将成为“javaSAFEscript”、“functionSAFEload”和“visionSAFEblurred”(!!)。

如果这可能适用于您,并且您坚持使用黑名单方法,请务必使用完全匹配的正则表达式以避免惹恼用户。换句话说,在安全性和可用性之间处于最佳状态,尽可能少地妥协。

于 2008-10-13T16:39:13.020 回答