什么是避免PHP网站中的xss攻击的最佳做法

我configuration了PHP,以便魔术引号处于打开状态,并且注册全局variablesclosures。

我尽我所能总是调用htmlentities()来输出从用户input派生的任何东西。

我也偶尔在我的数据库中查找附加的xss中常用的东西,例如…

<script 

我还应该做些什么?我怎样才能确保我所要做的事情总是完成。

对于成功的XSS预防,转义input不是最好的select。 也输出必须逃脱。 如果您使用Smarty模板引擎,您可以使用|escape:'htmlall'修饰符将所有敏感字符转换为HTML实体(我使用自己的|e修饰符,这是上面的别名)。

我的input/输出安全方法是:

  • 存储用户input没有修改(input没有HTML转义,只有通过PDO准备的语句完成数据库感知的转义)
  • 在输出上进行转义,具体取决于您使用的输出格式(例如,HTML和JSON需要不同的转义规则)

我认为在input过程中不应该逃避任何事情,而只能在输出中逃避。 由于(大部分时间)你不能假设你知道数据在哪里。 例如,如果您的表单需要获取稍后发送的电子邮件中的数据,则需要进行不同的转义(否则恶意用户可能会重写您的电子邮件标题)。

换句话说,你只能在数据“离开”你的应用程序的最后一刻逃脱:

  • 列表项目
  • 写入XML文件,转义为XML
  • 写入数据库,转义(对于特定的DBMS)
  • 写电子邮件,转义电子邮件
  • 等等

要简短:

  1. 你不知道你的数据在哪里
  2. 数据可能实际上最终在多个地方,需要不同的转义机制,但不是两个
  3. 数据为了错误的目标而逃跑真的不好。 (例如,收到一封电子邮件,题目是“去汤米的酒吧”。)

如果您在input层转义数据(或者您需要再次转义数据等),则会发生特效#3。

PS:我会第二个不使用magic_quotes的build议,那些是纯粹的邪恶!

有很多方法来做XSS(请参阅http://ha.ckers.org/xss.html ),这很难赶上。

我个人将其委托给我正在使用的当前框架(例如Code Igniter)。 虽然不完美,但它可能比我手工制作的例程更多。

这是一个很好的问题。

首先,除了使其安全地存储(例如放入数据库)之外,不要在input上转义文本。 这是因为你想保持input的内容,所以你可以用不同的方式和地点来描述它。 在此进行更改可能会影响您以后的演示文稿。

当你去显示你的数据过滤出什么不应该在那里。 例如,如果没有JavaScript的原因在那里search并将其删除。 一个简单的方法是使用strip_tags函数,只显示你允许的html标签。

接下来,把你有什么,并通过它认为htmlentities或htmlspecialchars改变那里有ascii字符。 根据上下文来做这件事,以及你想要做什么。

我也build议closures魔术语录。 它已经从PHP 6中删除,被认为是不好的做法使用它。 详情请见http://us3.php.net/magic_quotes

有关更多详情,请查阅http://ha.ckers.org/xss.html

这不是一个完整的答案,但希望足以帮助你开始。

rikh写道:

我尽我所能总是调用htmlentities()来输出从用户input派生的任何东西。

请参阅乔尔关于使代码看起来不对的帮助

我依靠PHPTAL 。

与Smarty和普通的PHP不同,它默认会转义所有的输出。 这对于安全来说是一个巨大的胜利,因为如果你忘记了htmlspecialchars()或者在某个地方|escape ,你的站点将不会变成一个可怕的站点。

XSS是HTML特定的攻击,所以HTML输出是防止它的正确的地方。 您不应该尝试对数据库中的数据进行预过滤,因为您可能需要将数据输出到另一个不接受HTML的介质,但有其自身的风险。

模板库。 或者至less,这是模板库应该做的。 为了防止XSS 所有的输出应该被编码。 这不是主要应用/控制逻辑的任务,它应该仅由输出方法来处理。

如果你在你的代码中添加了htmlentities(),那么总体devise是错误的。 正如你所build议的,你可能会错过一两个点。 这就是为什么唯一的解决scheme是严格的html编码– >输出variables写入html / xmlstream时。

不幸的是,大多数PHP模板库只添加自己的模板语法,但不关心输出编码,本地化,或HTMLvalidation,或任何重要的东西。 也许别人知道一个适当的模板库为PHP?

转移所有用户input对于大多数网站来说已经足够了。 还要确保会话ID不会在URL中结束,因此不能从Referer链接被盗取到另一个站点。 此外,如果您允许用户提交链接,请确保不允许javascript:协议链接; 这些会在用户点击链接时立即执行脚本。

如果您担心XSS攻击,则将输出string编码为HTML是解决scheme。 如果您记得将每个输出字符编码为HTML格式,则无法执行成功的XSS攻击。

了解更多信息: 清理用户数据:如何以及在哪里执行

就个人而言,我会禁用magic_quotes。 在PHP5 +中,默认情况下是禁用的,最好代码就好像它不存在一样,因为它不会逃避所有事情,它将从PHP6中移除。

接下来,取决于你正在过滤的用户数据types将决定接下来要做什么,例如,如果它只是文本,例如名称,则strip_tags(trim(stripslashes())); 它或检查范围使用正则expression式。

如果您期望某个范围的值,则创build一个有效值的数组,并且只允许这些值通过( in_array($userData, array(...)) )。

如果您正在检查数字,则使用is_numeric来强制执行整个数字或强制转换为特定types,这将防止人们尝试发送string。

如果您有PHP5.2 +,那么考虑查看filter()并使用可以过滤各种数据types(包括电子邮件地址)的扩展。 文档不是特别好,但正在改进。

如果你必须处理HTML,那么你应该考虑像PHPinputfilter或HTML净化器 。 HTML净化器也将validationHTML的一致性。 我不确定inputfilter是否仍在开发中。 两者都将允许您定义一组可以使用的标签以及允许的属性。

不pipe你决定什么,总要记住,永远不要信任任何来自用户(包括你自己)的PHP脚本。

所有这些答案都很好,但从根本上来说,XSS的解决scheme是通过string操作来停止生成HTML文档。

过滤input对于任何应用程序来说总是一个好主意。

使用htmlentities()和朋友转义您的输出应该工作,只要它正确使用,但这是通过连接string与mysql_real_escape_string($ var)创build一个SQL查询的HTML等效 – 它应该工作,但更less的事情可以validation您的工作可以这么说,与使用参数化查询的方法相比。

长期的解决scheme应该是应用程序在内部构build页面,也许使用像DOM这样的标准接口,然后使用库(如libxml)来处理到XHTML / HTML /等的序列化。 当然,我们距离stream行和速度还有很长一段路要走,但同时我们必须通过string操作来构build我们的HTML文档,这本质上是更危险的。

我发现使用这个函数有助于去掉很多可能的xss攻击: http : //www.codebelay.com/killxss.phps

“魔术引语”是对一些最严重的XSS漏洞的姑息治疗,这种漏洞通过逃避一切的input而工作,这是devise错误的。 唯一一个想要使用它的情况是绝对必须使用现有的PHP应用程序,这些应用程序已被认真写入XSS。 (在这种情况下,即使使用“魔术引号”,也会遇到严重的麻烦。)在开发自己的应用程序时,应禁用“魔术引号”,并遵循XSS安全规范。

当应用程序在其[X] HTML,CSS,ECMAscript或其他浏览器parsing的输出中包含来自外部来源的string(用户input,从其他网站获取的string等)时,会发生跨站点脚本攻击漏洞。 ([X] HTML),单引号或双引号(ECMAscript)等特殊字符将永远不会出现。 正确的解决方法是根据输出语言的规则总是转义string:使用[X] HTML中的实体,ECMAscript中的反斜杠等。

由于很难追踪不可信的内容,所以必须避免使用HTML这样的语言,而不是像“带标记的文本”这样的“文本string”。 一些编程环境通过引入几个不兼容的stringtypes:“string”(普通文本),“HTMLstring”(HTML标记)等等,使得它更容易。 这样,从“string”到“HTMLstring”的直接隐式转换将是不可能的,string成为HTML标记的唯一方式是通过转义函数传递。

“注册全局variables”,虽然禁用它绝对是一个好主意,处理完全不同于XSS的问题。

让你使用HttpOnly的任何会话cookie(或所有cookie)。 在这种情况下,大多数浏览器都会隐藏JavaScript的cookie值。 用户仍然可以手动复制cookie,但这有助于防止直接访问脚本。 StackOverflow在testing中遇到了这个问题。

这不是一个解决scheme,只是另一堵墙

  • 不要相信用户input
  • 转义所有自由文本输出
  • 不要使用magic_quotes; 看看是否有一个DBMS specfic变种,或使用PDO
  • 考虑尽可能使用仅限HTTP的cookie,以避免任何恶意脚本能够劫持会话

你至less应该validation进入数据库的所有数据。 并尝试validation离开数据库的所有数据。

mysql_real_escape_string是很好的防止SQL注入,但XSS更棘手。 你应该尽可能地preg_match,stip_tags或者htmlentities!

HTML Purifier(http://htmlpurifier.org/)是防止PHP应用程序中的XSS的最佳方法。; 它的一个小缺点是它是一个相当大的库,最好和APC这样的操作码caching一起使用。 你可以在任何不可信内容输出到屏幕的地方使用它。 htmlentities,htmlspecialchars,filter_input,filter_var,strip_tags等等更彻底。

使用现有的用户input清理库来清理所有的用户input。 除非你付出很大的努力,否则自己实施它永远不会工作。

我发现最好的方法是使用一个允许你绑定你的代码的类,这样你就不用担心手动转义你的数据。

在一个不会导致错误警报的站点上实施一个完整的sql注入/ xss注入防护是很困难的。 在CMS中,最终用户可能希望使用链接到来自其他站点的项目的<script><object>

我build议让所有用户用NoScript安装FireFox 😉