我尽我所能地始终对我从用户输入派生的任何输出调用htmlentities()。
我有时还会在数据库中查找xss附件中常用的东西,例如...
<script
我还应该做些什么以及如何做?确保我要尝试做的事情总是能完成。
#1 楼
为了成功防止XSS,逃避输入并不是最好的选择。输出也必须转义。如果使用Smarty模板引擎,则可以使用|escape:'htmlall'
修饰符将所有敏感字符转换为HTML实体(我使用自己的|e
修饰符,这是上面的别名)。 :存储用户输入未修改(输入不转义HTML,仅通过PDO准备的语句完成DB感知转义)
输出转义,具体取决于您的输出格式使用(例如HTML和JSON需要不同的转义规则)
#2 楼
我认为,在输入过程中,不应仅在输出中逃避任何操作。由于(在大多数情况下)您不能假设您知道数据的去向。例如,如果您有一个采用稍后接收到的数据的表单,则您需要进行不同的转义(否则恶意用户可能会重写您的电子邮件标题)。换句话说,您只能在数据“离开”应用程序的最后一刻转义:
列出项目
写入XML文件,用于XML的转义
写入数据库,用于特定DBMS的转义,
编写电子邮件,用于电子邮件转义,
等/>
您不知道数据的去向
数据实际上可能会在一个以上的地方结束,需要使用不同的转义机制,但又不能同时
错误的目标真的不是很好。 (例如,收到一封主题为“转到Tommy's bar”的电子邮件。)
如果在输入层转义数据(或者需要再次转义该数据),则会发生第3步。 ,等等)。
PS:我将建议不要使用magic_quotes,这是纯粹的邪恶!
评论
奖金回合:由于对输入(而非输出)进行了过滤,WordPress在2015年通过MySQL列截断被XSS拥有。
–斯科特·阿西塞夫斯基(Scott Arciszewski)
15年7月30日在2:13
#3 楼
有很多方法可以执行XSS(请参阅http://ha.ckers.org/xss.html),而且很难掌握。我亲自将其委托给当前的框架m使用(例如Code Igniter)。虽然不完美,但它可能比我手工制作的例程捕获的更多。
#4 楼
这是一个很大的问题。首先,不要输入时转义文本,除非要确保它可以安全存储(例如放入数据库中)。这样做的原因是您想保留输入的内容,以便可以不同的方式和位置在上下文中呈现它。在此处进行更改可能会损害您以后的演示文稿。
当您演示数据时,请过滤掉不应该存在的内容。例如,如果没有理由在其中搜索javascript,然后将其删除。一种简单的方法是使用strip_tags函数,仅显示允许的html标签。
接下来,获取您拥有的内容,并传递给htmlentities或htmlspecialchars以将其中的内容更改为ASCII字符。根据上下文和您想要获得的结果来执行此操作。
我也建议关闭Magic Quotes。它已从PHP 6中删除,使用它被认为是不好的做法。有关详细信息,请参见http://us3.php.net/magic_quotes
有关更多详细信息,请访问http://ha.ckers.org/xss.html
,这是“一个完整的答案,但希望足以帮助您入门。
#5 楼
rikh写道:
我竭尽所能,始终对我从用户输入派生的任何输出调用htmlentities()。乔尔(Joel)的“使代码看起来错误”的文章可帮助您解决此问题
#6 楼
模板库。或至少是模板库应该这样做。为防止XSS,应对所有输出进行编码。这不是主要应用程序/控制逻辑的任务,它应该仅由输出方法处理。
如果在代码中不使用htmlentities(),则总体设计是错误的。正如您所建议的,您可能会错过一两个地方。
这就是为什么唯一的解决方案是严格的html编码->当将输出vars写入html / xml流时。
,大多数php模板库仅添加自己的模板语法,而与输出编码,本地化或html验证或任何重要内容无关。也许其他人知道适合php的模板库?
评论
我完全同意,我会说最好的模板库是xsl。
–约西亚
2010-4-18的2:11
#7 楼
我要依靠PHPTAL。与Smarty和普通的PHP不同,它默认情况下会转义所有输出。这是安全方面的一大胜利,因为如果您忘记在某个地方使用
htmlspecialchars()
或|escape
,您的网站将不会受到攻击。XSS是HTML特定的攻击,因此HTML输出是防止它的正确位置。您不应该尝试对数据库中的数据进行预过滤,因为您可能需要将数据输出到不接受HTML但有其自身风险的另一种介质。
评论
SQL不执行JavaScript。将数据转换为HTML,SQL,邮件等通用的安全子集过于局限,不能完全消除风险。正确转义HTML输出对于HTML是防弹的。为使SQL正确转义,请使用SQL工具!
–内核
08年11月1日在19:59
#8 楼
对于大多数站点,转义所有用户输入就足够了。另外,请确保会话ID不在URL中,以免它们从Referer
链接到另一个站点的过程中被盗。此外,如果您允许用户提交链接,请确保不允许javascript:
协议链接;用户点击链接后,这些脚本就会执行脚本。#9 楼
如果您担心XSS攻击,则将输出字符串编码为HTML是解决方案。如果您记得将每个输出字符编码为HTML格式,则无法执行成功的XSS攻击。更多信息:
对用户数据进行消毒:如何以及在何处进行
#10 楼
就个人而言,我将禁用magic_quotes。在PHP5 +中,默认情况下将其禁用,最好将其编码为根本不存在,因为它无法逃避一切,并且会从PHP6中删除。您正在过滤的用户数据将决定下一步该做什么,例如如果只是文字,例如一个名称,然后使用strip_tags(trim(stripslashes()));
对其进行命名或使用正则表达式检查范围。如果期望某个范围的值,请创建一个有效值数组,并仅允许这些值通过(
in_array($userData, array(...))
)。 br /> 如果要检查数字,请使用is_numeric强制执行整数或强制转换为特定类型,这应该可以防止人们尝试代替发送字符串。
如果您使用的是PHP5.2 +然后考虑查看filter()并利用该扩展名可以过滤各种数据类型,包括电子邮件地址。文档不是特别好,但是正在改进。
如果必须处理HTML,则应考虑使用类似PHP Input Filter或HTML Purifier的工具。 HTML Purifier还将验证HTML的一致性。我不确定输入过滤器是否仍在开发中。两者都将允许您定义一组可以使用的标记以及允许使用哪些属性。
无论您做出什么决定,都请记住,永远不要相信任何来自用户的PHP脚本(包括你自己!)。
#11 楼
所有这些答案都是不错的选择,但是从根本上说,解决XSS的方法是停止通过字符串操作生成HTML文档。过滤输入对于任何应用程序都是一个好主意。 />只要使用正确,使用htmlentities()和朋友转义输出就应该可以正常工作,但这在HTML上等效于通过使用mysql_real_escape_string($ var)连接字符串来创建SQL查询-它应该可以工作,但是可以验证的事情更少与使用参数化查询之类的方法相比,可以说您的工作。使用库(如libxml)来处理到XHTML / HTML / etc的序列化。当然,要使它流行并且足够快还需要很长的路要走,但是与此同时,我们必须通过字符串操作来构建HTML文档,这本质上更具风险。
#12 楼
我发现使用此功能有助于消除很多可能的xss攻击:http://www.codebelay.com/killxss.phps
#13 楼
对于某些最严重的XSS缺陷,“魔术引号”是一种姑息疗法,该缺陷可以通过转义输入中的所有内容而起作用,这在设计上是错误的。唯一要使用它的情况是,您必须绝对使用已知的XSS粗心编写的现有PHP应用程序时。 (在这种情况下,即使使用“魔术引号”,您也会遇到严重麻烦。)在开发自己的应用程序时,应禁用“魔术引号”,而应遵循XSS安全的惯例。XSS,跨站点脚本漏洞,当应用程序在其[X] HTML,CSS,ECMAscript或其他浏览器解析的输出中包含来自外部源(用户输入,从其他网站等获取的字符串)的字符串而没有适当的转义时,会发生这种情况,希望小于号([X] HTML),单引号或双引号(ECMAscript)之类的字符将永远不会出现。正确的解决方案是始终根据输出语言的规则对字符串进行转义:使用[X] HTML中的实体,ECMAscript中的反斜杠等。
因为很难跟踪内容是不受信任的并且必须转义,所以最好始终转义“文本字符串”而不是诸如HTML之类的“带有标记的文本”的所有内容。某些编程环境通过引入几种不兼容的字符串类型使之更容易:“字符串”(普通文本),“ HTML字符串”(HTML标记)等等。这样,就不可能从“字符串”直接隐式转换为“ HTML字符串”,并且字符串成为HTML标记的唯一方法是将其传递给转义函数。
“注册全局变量”,尽管禁用它绝对是一个好主意,但处理的问题与XSS完全不同。
评论
不要使用全局寄存器。它们使编写不安全的代码变得容易,并且自发布以来就已经贬值了。
–詹姆斯
2010-09-15 18:33
我的意思是禁用全局寄存器,当然不启用。错别字。
–阿列克谢·费尔德根德勒
2010年11月11日15:49
#14 楼
使您使用HttpOnly的任何会话cookie(或所有cookie)成为可能。在这种情况下,大多数浏览器都会从JavaScript隐藏cookie值。用户仍然可以手动复制cookie,但这有助于防止直接脚本访问。 StackOverflow在Beta期间出现此问题。这不是解决方案,只是墙里的另一块砖
#15 楼
不信任用户输入
转义所有自由文本输出
不使用magic_quotes;查看是否存在特定于DBMS的变体,或使用PDO
考虑使用仅HTTP cookie,以免任何恶意脚本能够劫持会话
#16 楼
您至少应验证进入数据库的所有数据。并尝试验证所有离开数据库的数据。mysql_real_escape_string可以很好地防止SQL注入,但XSS则比较棘手。
应尽可能进行preg_match,stip_tags或htmlentities!
#17 楼
当前,在PHP应用程序中防止XSS的最佳方法是HTML Purifier(http://htmlpurifier.org/)。它的一个小缺点是它是一个相当大的库,最好与APC这样的操作码缓存一起使用。您可以在任何不受信任的内容输出到屏幕的地方使用它。 htmlentities,htmlspecialchars,filter_input,filter_var,strip_tags等更为全面。#18 楼
使用现有的用户输入清理库来清理所有用户输入。除非您付出很多努力,否则您自己也无法实现。#19 楼
我发现最好的方法是使用一个类,该类允许您绑定代码,因此您不必担心手动转义数据。#20 楼
很难在不会引起错误警报的站点上实施全面的sql injection / xss注入预防。在CMS中,最终用户可能希望使用链接到另一个站点中项目的<script>
或<object>
。 我建议所有用户使用NoScript安装FireFox ;-)
评论
htmlentities()是一个矫kill过正,并且对编码敏感。 htmlspecialchars()也能提供保护。
–内核
08-10-16在18:37
htmlspecialchars可能不是您的朋友:stackoverflow.com/questions/110575/…
–Cheekysoft
09-10-13在9:32
我认为最好先转义,然后再将其保存在数据库中,因为这样一来,您只需要转义一次,但是如果您仅将它存储在数据库中并转义,那么每次用户访问站点时都会使服务器工作量增加。而且大多数转义对于PHP和Node.js都是相同的。所以更好的逃脱,然后保存。
–艾里
2014年1月31日在22:35
@AbdulJabbarWebBestow绝对不是。数据库是一个以输出不可知格式存储数据的地方。不同的输出设备需要不同的转义规则,因此,在访问数据库之前先转义HTML输出,就可以避免编写API,PDF导出等内容。不必担心服务器负载。这是他们的工作。
–MichałRudnicki
2014年2月2日在10:46
@AbdulJabbarWebBestow Quotes " need to be escaped as " for use in HTML, but \" for use in most other languages.
– Mr Lister
Dec 17 '15 at 11:57