PHP XSS 清洗

7

问题:

为了避免UTF8编码的页面受到XSS攻击,最好使用哪些safe1()、safe2()、safe3()和safe4()函数?在所有浏览器中(特别是IE6)是否也安全?

<body><?php echo safe1($xss)?></body>

<body id="<?php echo safe2($xss)?>"></body>

<script type="text/javascript">
  var a = "<?php echo safe3($xss)?>";
</script>

<style type="text/css">
  .myclass {width:<?php echo safe4($xss)?>}
</style>

许多人说,最好的方法是:
// safe1 & safe2
$s = htmlentities($s, ENT_QUOTES, "UTF-8");

// But how would you compare the above to:
//    https://github.com/shadowhand/purifier
// OR http://kohanaframework.org/3.0/guide/api/Security#xss_clean
// OR is there an even better if not perfect solution?

.

// safe3
$s = mb_convert_encoding($s, "UTF-8", "UTF-8");
$s = htmlentities($s, ENT_QUOTES, "UTF-8");

// How would you compare this to using using mysql_real_escape_string($s)?
// (Yes, I know this is a DB function)
// Some other people also recommend calling json_encode() before passing to htmlentities
// What's the best solution?

关于PHP和XSS有很多帖子。 大部分只是说“使用HTMLPurifier”或“使用htmlspecialchars”,或者是错误的。 其他人建议使用OWASP,但速度极慢。 以下是我找到的一些好文章:

Do htmlspecialchars和mysql_real_escape_string可以保护我的PHP代码免受注入攻击吗?

XSS Me Warnings - 真正的XSS问题?

CodeIgniter - 为什么要使用xss_clean


非转义字符不是你唯一需要担心的事情。在你的 var a = "<?php echo safe3($xss)?>"; 中,你还需要剥离所有换行符。 - zerkms
2个回答

4

safe2() 明显是 htmlspecialchars()

你应该使用 HTMLPurifier 替代 safe1() 来清理完整的 HTML 代码块。它会去除不需要的属性、标签和任何 JavaScript 相关的内容。是的,它比较慢,但它可以覆盖所有小的边缘情况(甚至是旧版的 IE),从而让用户安全地重复使用 HTML 片段。但是请查看 http://htmlpurifier.org/comparison 以了解其他替代方案。-- 如果你只想显示原始的用户文本(没有过滤的 HTML),那么 htmlspecialchars(strip_tags($src)) 就可以正常工作。

safe3() 暴力使用正则表达式。在这里,你只能对你实际需要的内容应用一个 白名单

var a = "<?php echo preg_replace('/[^-\w\d .,]/', "", $xss)?>";

当然,你可以使用json_encode在此处获取完全有效的JS语法和变量。但是这样,你只是将该字符串的可利用性延迟到JS代码中,然后你必须对其进行监控。


在所有浏览器(特别是IE6)中也安全吗?

如果明确指定字符集,则IE将不会执行其可怕的内容检测魔法,因此可以忽略UTF7漏洞。


对于safe2:为什么htmlspecialchars($s, ENT_QUOTES, "UTF-8")比htmlentities($s, ENT_QUOTES, "UTF-8")更好?它们是等效的,只是前者更快吗?我听说后者更好,因为它可以防止外来字符的XSS攻击。您能否通过给我一个例子来扩展您所说的“但是你只是延迟了在您的JS代码中利用该字符串”的意思?谢谢! - user324289
不,它们大多数是相同的。htmlentities还编码了一些其他字符。但由于假XHTML仍然很普遍,您应该更喜欢只使用XML转义的htmlspecialchars,而不是可能无效的HTML实体。对于XSS攻击来说,外国字符并不是太大的问题。更严重的是未引用的属性,因为不仅"'在那里有问题,而且@ ! %和其他字符也可能成为终止符。 - mario
还有一个问题:对于上面的safe4,哪个函数是合适的?(我编辑了原帖) - user324289
HTMLPurifier 包含一个 CSS 清理器,不确定它是否适用于此处。(可能有单独的类。)我会再次使用限制性正则表达式,但这不会处理 IE 的 CSS 漏洞,除非您禁止括号。 - mario
1
此外,对于 safe4;它取决于上下文。通常针对 AZaz09 "'# 的正则表达式应该非常有效 (请注意,这里的;:是最危险的字符)。还要注意,某些字体名称需要奇怪的字符。但是,如果您只是为了简单的 CSS 关键字(如 solidred)或度量单位(如 2px5em 9px),那么这就足够了。 - Christian
显示剩余5条评论

3
请注意第三个可选参数接受字符编码,应使用它替代mv_convert_encoding。只要PHP文件本身保存为UTF8编码即可正常工作。

http://php.net/htmlentities(请注意可选的第三个参数,可以指定字符编码。建议使用该选项而不是mv_convert_encoding。只要PHP文件本身采用UTF8编码保存即可)。

htmlentities($s, ENT_COMPAT, 'UTF-8');

关于直接将变量注入到Javascript中,您可以考虑将内容放入页面中其他地方的隐藏HTML元素中,并在需要时从DOM中提取内容。
您提到的净化器是用于在实际显示用户提交的HTML时使用的(即允许浏览器实际呈现)。使用htmlentities将对所有内容进行编码,以便字符将在UI中显示,但浏览器不会解释任何实际的代码。您想要做什么?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接