我配置了PHP,以便启用魔术引号并关闭注册全局。
我会尽力为我输出的任何来自用户输入的内容调用htmlentities()。
我偶尔也会搜索我的数据库,以获取xss附带的常用内容,例如...
<script
我还应该做些什么,以及如何确保我要做的事情始终完成。
答案 0 :(得分:58)
逃避输入并不是您成功预防XSS的最佳选择。还必须转义输出。如果您使用Smarty模板引擎,则可以使用|escape:'htmlall'
修饰符将所有敏感字符转换为HTML实体(我使用自己的|e
修饰符,这是上面的别名。)
我的输入/输出安全性方法是:
答案 1 :(得分:18)
我认为在输入过程中不应该逃避任何事情,只能在输出上。因为(大部分时间)你不能假设你知道数据的去向。例如,如果您的表单中包含稍后显示在您发送的电子邮件中的数据,则需要进行不同的转义(否则恶意用户可能会重写您的电子邮件标题)。
换句话说,您只能在数据“离开”您的应用程序的最后时刻逃脱:
简而言之:
如果您在输入图层转义数据(或者您需要再次对其进行转义等),则会出现Esp#3。
PS:我会提出不使用magic_quotes的建议,那些是纯粹的邪恶!
答案 2 :(得分:12)
有许多方法可以做XSS(参见http://ha.ckers.org/xss.html)并且很难捕捉到。
我个人将此委托给我正在使用的当前框架(例如Code Igniter)。虽然不完美,但它可能比我手工制作的程序更有效。
答案 3 :(得分:10)
这是一个很好的问题。
首先,除了使其安全存储(例如放入数据库)之外,不要在输入上转义文本。这样做的原因是您希望保留输入的内容,以便您可以以不同的方式和位置进行上下文显示。在此处进行更改可能会影响您之后的演示。
当你去展示你的数据过滤掉不应该存在的东西时。例如,如果javascript没有理由在那里搜索并删除它。一种简单的方法是使用strip_tags函数并仅显示您允许的html标记。
接下来,拿走你所拥有的并通过它认为htmlentities或htmlspecialchars来改变那里的ascii字符。根据上下文和你想要的内容来做这件事。
我也建议关闭Magic Quotes。它已从PHP 6中删除,被认为是使用它的不良做法。详情请见http://us3.php.net/magic_quotes
有关详细信息,请查看http://ha.ckers.org/xss.html
这不是一个完整的答案,但希望足以帮助你开始。
答案 4 :(得分:7)
rikh写道:
我会尽力为我输出的任何来自用户输入的内容调用htmlentities()。
请参阅Joel在Making Code Look Wrong上的论文以获取有关此
的帮助答案 5 :(得分:4)
模板库。或者至少,这就是模板库应该做的事情。 要防止XSS 所有输出都应编码。这不是主应用程序/控制逻辑的任务,它应该只由输出方法处理。
如果你在代码中撒上htmlentities(),整体设计是错误的。正如你的建议,你可能会错过一两个地方。 这就是为什么唯一的解决方案是严格的html编码 - &gt;当输出变量被写入html / xml流时。
不幸的是,大多数php模板库只添加自己的模板语法,但不关心输出编码,本地化,html验证或任何重要的事情。也许别人知道一个适合php的模板库?
答案 6 :(得分:4)
我依靠PHPTAL。
与Smarty和普通PHP不同,默认情况下它会转义所有输出。这对安全性来说是一个巨大的胜利,因为如果您忘记某处htmlspecialchars()
或|escape
,您的网站就不会变得难以理解。
XSS是特定于HTML的攻击,因此HTML输出是防止它的正确位置。您不应该尝试在数据库中预过滤数据,因为您可能需要将数据输出到另一个不接受HTML的介质,但是它有自己的风险。
答案 7 :(得分:2)
所有这些答案都很棒,但从根本上说,XSS的解决方案是停止通过字符串操作生成HTML文档。
对任何应用程序来说,过滤输入总是一个好主意。
使用htmlentities()转义输出,并且朋友应该正常工作,但是这相当于通过将字符串与mysql_real_escape_string($ var)连接来创建SQL查询 - 它应该可以工作,但是可以减少与使用参数化查询等方法相比,可以确认您的工作。
长期解决方案应该是应用程序在内部构建页面,可能使用像DOM这样的标准接口,然后使用库(如libxml)来处理到XHTML / HTML /等的序列化。当然,我们距离流行和足够快的人还有很长的路要走,但与此同时我们必须通过字符串操作来构建我们的HTML文档,这本身就更具风险。
答案 8 :(得分:2)
我发现使用此功能有助于消除许多可能的xss攻击: http://www.codebelay.com/killxss.phps
答案 9 :(得分:2)
对于大多数网站来说,转义所有用户输入就足够了。还要确保会话ID不会在URL中结束,因此不能从Referer
链接中窃取到其他站点。此外,如果您允许用户提交链接,请确保不允许javascript:
协议链接;一旦用户点击链接,这些就会执行一个脚本。
答案 10 :(得分:2)
就个人而言,我会禁用magic_quotes。在PHP5 +中,默认情况下它被禁用,最好是编码,好像它根本不存在,因为它不会逃避所有内容,它将从PHP6中删除。
接下来,根据您过滤的用户数据类型,将决定下一步做什么,例如如果它只是文字,例如一个名称,然后strip_tags(trim(stripslashes()));
它或检查范围使用正则表达式。
如果您期望某个值范围,请创建一个有效值数组,并仅允许这些值通过(in_array($userData, array(...))
)。
如果要检查数字,请使用is_numeric强制执行整数或转换为特定类型,这样可以防止人们尝试发送字符串。
如果你有PHP5.2 +,那么考虑查看filter()并使用可以过滤各种数据类型(包括电子邮件地址)的扩展名。文档不是特别好,但正在改进。
如果您必须处理HTML,那么您应该考虑PHP Input Filter或HTML Purifier之类的内容。 HTML Purifier还将验证HTML的一致性。我不确定输入过滤器是否仍在开发中。两者都允许您定义一组可以使用的标记以及允许的属性。
无论你决定什么,永远记住,永远不要相信任何来自用户(包括你自己!)的PHP脚本。
答案 11 :(得分:2)
XSS是一个跨站点脚本漏洞,当应用程序在其[X] HTML,CSS,ECMAscript或其他浏览器解析的输出中包含来自外部源(用户输入,从其他网站获取等)的字符串时,会发生XSS逃避,希望永远不会出现像小于(在[X] HTML中),单引号或双引号(ECMAscript)这样的特殊字符。对它的正确解决方案是始终根据输出语言的规则转义字符串:使用[X] HTML中的实体,ECMAscript中的反斜杠等。
因为很难跟踪不受信任且必须被转义的内容,所以总是要逃避所有“文本字符串”而不是像HTML这样的语言中的“带标记的文本”。一些编程环境通过引入几个不兼容的字符串类型使其变得更容易:“string”(普通文本),“HTML字符串”(HTML标记)等。这样,从“字符串”到“HTML字符串”的直接隐式转换是不可能的,字符串可以成为HTML标记的唯一方法是将其传递给转义函数。
“注册全局”虽然禁用它绝对是一个好主意,但它处理的问题与XSS完全不同。
答案 12 :(得分:2)
如果您担心XSS攻击,将输出字符串编码为HTML就是解决方案。如果您记得将每个输出字符编码为HTML格式,则无法执行成功的XSS攻击。
答案 13 :(得分:1)
答案 14 :(得分:1)
为您提供您使用HttpOnly的任何会话cookie(或所有cookie)。在这种情况下,大多数浏览器都会隐藏JavaScript的cookie值。用户仍然可以手动复制cookie,但这有助于防止直接访问脚本。 StackOverflow在测试版中遇到了这个问题。
这不是解决方案,只是墙上的另一块砖
答案 15 :(得分:1)
您至少应该验证进入数据库的所有数据。并尝试验证离开数据库的所有数据。
mysql_real_escape_string可以防止SQL注入,但XSS比较棘手。 你应该尽可能preg_match,stip_tags或htmlentities!
答案 16 :(得分:1)
在PHP应用程序中防止XSS的最佳方法是HTML Purifier(http://htmlpurifier.org/)。它的一个小缺点是它是一个相当大的库,最好与像APC一样的操作码缓存使用。您可以在任何不受信任的内容输出到屏幕的地方使用它。 htmlentities,htmlspecialchars,filter_input,filter_var,strip_tags等等更彻底。
答案 17 :(得分:0)
使用现有的用户输入清理库清除所有用户输入。除非你把很多的努力投入其中,否则自己实施它将永远不会有效。
答案 18 :(得分:0)
我发现最好的方法是使用一个允许您绑定代码的类,这样您就不必担心手动转义数据。
答案 19 :(得分:-1)
在不会导致错误警报的站点上实施彻底的SQL注入/ xss注入防护很困难。在CMS中,最终用户可能希望使用链接到其他网站上的项目的<script>
或<object>
。
我建议让所有用户使用NoScript安装FireFox; - )