防止服务端脚本和跨站脚本攻击(XSS)

5
有没有现成的PHP / MySQL脚本可以用来防止服务器端脚本和JS注入?
我知道一些典型的函数,如htmlentities、特殊字符、字符串替换等等,但是否有一个简单的代码或函数可以对所有情况都是安全的呢?
任何想法都很棒。非常感谢:)
编辑:有些通用的东西可以剥离掉任何可能危险的东西,比如大于/小于符号、分号、像“DROP”这样的单词等等?
我基本上只想把所有东西压缩成字母数字,我猜...?

1
你是不是想说“跨站点脚本”而不是“服务器端脚本”?或者你是在指远程代码包含/执行? - janmoesen
7个回答

5

永远不要向HTML流输出任何未经过htmlspecialchars()处理的数据位,这样就可以消除任何XSS风险。这是一个简单易行的规则,容易遵循。

虽然如此,作为程序员,这是您的工作。

您可以定义

function h(s) { return htmlspecialchars(s); }

如果在PHP文件中写100次htmlspecialchars()太长了。另一方面,使用htmlentities()则完全没有必要。
重点是:有代码和数据两种。如果你混合使用它们,则会发生不好的事情。
对于HTML来说,代码是元素、属性名、实体、注释。数据则是其他所有内容。数据必须进行转义以避免被误认为是代码。
对于URL来说,代码是协议、主机名、路径、查询字符串的机制(包括?&=#)。数据是查询字符串中的所有内容:参数名称和值。确保它们不被错认为是代码,必须进行转义。
嵌入HTML中的URL必须进行双重转义(通过URL转义和HTML转义),以确保代码和数据正确分离。
现代浏览器能够将极其错误或不正确的标记解析为有用的东西。虽然这种能力很强大,但也不应过度依赖。某些事情之所以能够工作(如未对<a href>中的URL进行适当的HTML转义),并不意味着这样做就是好的或正确的。跨站脚本攻击是一个问题,起因是a)人们不知道数据/代码分离(即"转义"),或者他们粗心大意,以及b)试图聪明地规避数据中无需转义的内容。
只要确保不属于a)和b)类别,就可以轻松避免跨站脚本攻击。

不,它不会。如果您将其放置为文本节点,则是安全的(假设它不在脚本或样式元素内)。另一方面,属性值呢?<img src="javascript:xss()">(现在大多数浏览器都可以防止这种情况,但还存在其他风险) - Quentin
好的,但是如果用户将 SQL 提交到 URL 中怎么办?例如:"DROP table users" - Tim
我会说:“永远不要输出任何用户提供的数据”。网站模板可能会避免这种危险 :) - Your Common Sense
@Tim:对于 SQL,你应该使用参数化查询(mysqli_* 或 PDO)。因为它们可以完全消除 SQL 注入。 - Tomalak
htmlspecialchars 单独使用不安全。请参考 http://stackoverflow.com/questions/2964424/to-htmlencode-or-not-to-htmlencode-user-input-on-web-form-asp-net-vb/2965444#2965444。 - Cheekysoft
显示剩余4条评论

3

我认为Google-caja可能是一个解决方案。我编写了一款用于检测和自动预防Java Web应用程序中的XSS攻击的污点分析器,但不适用于PHP。我认为学习使用caja对Web开发人员来说是个好东西。


1

没有。风险取决于您对数据的处理方式,您无法编写使数据对所有情况都安全的程序(除非您想丢弃大部分数据)。


是的,但是当涉及到网络和PHP时,我们并不是如此泛泛地说话。显然,您将希望禁用某些字符和字符串,因此如果可能的话,我想要一个相当通用的列表。我基本上只需要字母数字信息。 - Tim
哪些字母?你想禁止人们使用连字符和句号吗?事情很少有那么简单。 - Quentin

1
有没有一个简单的代码或函数可以对所有情况进行故障保护?
没有。
离开 PHP 的数据表示必须根据其去向进行特定的转换/编码。因此,应该仅在离开 PHP 的地方进行转换/编码。
C.

0
你可以参考OWASP来更深入了解XSS攻击。

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

为了避免 JavaScript 攻击,你可以尝试使用开源卓越提供的这个项目。

https://www.opensource-excellence.com/shop/ose-security-suite.html

我的网站以前遭受过JS攻击,但是这个工具每天都帮我阻止所有的攻击。我认为它可以帮助你们避免这个问题。

此外,你可以在你的PHP脚本中添加一个过滤器来过滤所有的JS攻击,这里有一个可以完成任务的模式:

if (preg_match('/(?:[".]script\s*()|(?:\$\$?\s*(\s*[\w"])|(?:/[\w\s]+/.)|(?:=\s*/\w+/\s*.)|(?:(?:this|window|top|parent|frames|self|content)[\s*[(,"]\s[\w\$])|(?:,\s*new\s+\w+\s*[,;)/ms', strtolower($POST['VARIABLENAME']))) { filter_variable($POST['VARIABLENAME']); }


-1
回答你的问题:除了<>符号以外,其他都与XSS无关。而htmlspecialchars()可以处理它们。
页面文本中出现DROP table这个词并不会造成任何伤害 ;)

那么如果要使用 " 来关闭属性,然后继续编写自己的代码呢?<img src="user-supplied-stuff" onerror="alert(document.cookie)"> 看起来对我来说有点 XSS。 :-) - janmoesen
@janm htmlspecialchars 会捕获双引号,所以你最终应该得到 <img src="user-supplied-stuff&quot; onerror=&quot;alert(document.cookie)">。但是对于图片,你应该先检查图片是否存在,以避免出现损坏的图片。 - DisgruntledGoat
这并不正确。请参见http://stackoverflow.com/questions/2964424/to-htmlencode-or-not-to-htmlencode-user-input-on-web-form-asp-net-vb/2965444#2965444。 - Cheekysoft
@DisgruntledGoat:我的评论是关于错误的说法“除了<>符号之外,其他都与XSS无关。” - janmoesen

-3

为了清洁用户数据,请使用html_special_chars(); str_replace()和其他函数来剪切不安全的数据。


mysql_escape_string已被弃用,无法正确处理字符编码。 - Quentin
好的。在这种情况下,你可以使用 str_replace 来清理你的请求。 - GOsha
1
str_replace 更糟糕。get_magic_quotes_gpc 与数据库转义无关。整个函数概念很愚蠢 - 它会进行双重转义! - Your Common Sense
请写一个好的函数来防止这些麻烦。我知道你有这样的技能))) 如果没有,也只需要花费你5分钟))) - GOsha
1
要将一些数据放入mysql查询中,您可以使用$data="'".mysql_real_escape_string($data)."'";或绑定。还有一些关于运算符/标识符的规则。但这与XSS无关。 - Your Common Sense
谢谢。我知道这与XSS无关,这是为了我自己。 - GOsha

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