it-swarm.cn

避免XSS攻击的最佳做法是什么? PHP 现场

我已配置PHP,以便启用魔术引号并关闭注册全局变量。

我会尽力为我输出的任何来自用户输入的内容调用htmlentities()。

我偶尔也会搜索我的数据库,以获取xss附带的常用内容,例如...

<script

我还应该做些什么,以及如何确保我想要做的事情是 总是 完成。

65
Rik Heywood

逃避输入并不是您成功实施XSS预防的最佳选择。还必须转义输出。如果你使用Smarty模板引擎,你可以使用|escape:'htmlall'修饰符将所有敏感字符转换为HTML实体(我使用自己的|e修饰符,它是上面的别名)。

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

  • 存储用户输入未修改(输入时没有HTML转义,只能通过PDO预处理语句完成数据库感知转义)
  • 输出中的转义,取决于您使用的输出格式(例如,HTML和JSON需要不同的转义规则)
58
Michał Rudnicki

我认为在输入期间不应该逃避任何事情,只能在输出上。因为(大部分时间)你不能假设你知道数据的去向。例如,如果您的表单中包含稍后显示在您发送的电子邮件中的数据,则需要进行不同的转义(否则恶意用户可能会重写您的电子邮件标题)。

换句话说,您只能在数据“离开”应用程序的最后时刻转义:

  • 项目清单
  • 写入XML文件,转义为XML
  • 写入DB,转义(对于特定的DBMS)
  • 写电子邮件,转发电子邮件
  • 等等

简而言之:

  1. 您不知道数据的去向
  2. 数据实际上最终可能会出现在多个地方,需要不同的转义机制,但不能同时使用
  3. 针对错误目标逃脱的数据真的不太好。 (例如,收到一封主题为“去汤米的酒吧”的电子邮件。)

如果您在输入层转义数据(或者您需要再次对其进行转义等),则会出现Esp#3。

PS:我会提出不使用magic_quotes的建议,这些都是纯粹的邪恶!

18
Jilles

有很多方法可以做XSS(参见 http://ha.ckers.org/xss.html )并且很难理解。

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

12
Christian Studer

这是一个很好的问题。

首先,除了使其安全存储(例如放入数据库)之外,不要在输入上转义文本。这样做的原因是您希望保留输入的内容,以便您可以以不同的方式和位置进行上下文显示。在此处进行更改可能会影响以后的演示。

当你去展示你不应该存在的数据时。例如,如果javascript没有理由在那里搜索并删除它。一个简单的方法是使用 strip_tags 函数,只显示你允许的html标签。

接下来,拿走你所拥有的并传递它的想法htmlentities或htmlspecialchars来改变那里的ascii字符。根据上下文和你想要的内容来做这件事。

我也建议关闭Magic Quotes。它已从PHP 6中删除,被认为是使用它的不良做法。详细信息在 http://us3.php.net/magic_quotes

有关详细信息,请查看 http://ha.ckers.org/xss.html

这不是一个完整的答案,但希望足以帮助您入门。

10
Matt Farina

我会尽力为我输出的任何来自用户输入的内容调用htmlentities()。

.

See Joel's essay on Making Code Look Wrong for help with this

7
Mason

我依靠 _ phptal _ 为此。

与Smarty和普通PHP不同,默认情况下它会转义所有输出。这对安全性来说是一个巨大的胜利,因为如果你在某个地方忘记htmlspecialchars()|escape,你的网站就不会变得难以理解。

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

4
Kornel

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

如果你在代码中撒上htmlentities(),整体设计是错误的。正如你的建议,你可能会错过一两个地方。这就是为什么唯一的解决方案是严格的html编码 - >当 输出变量被写入html/xml流时。

不幸的是,大多数php模板库只添加自己的模板语法,但不关心输出编码,本地化或html验证,或任何重要的事情。也许别人知道一个适合php的模板库?

4
user319490

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

阅读更多: 消毒用户数据:如何以及在何处进行

2
Niyaz

就个人而言,我会禁用magic_quotes。在PHP5 +中它默认是禁用的,并且最好是编码,好像它根本不存在,因为它不会逃避所有内容,它将从PHP6中删除。

接下来,根据您过滤的用户数据类型,将决定下一步做什么,例如如果它只是文字,例如一个名称,然后strip_tags(trim(stripslashes()));它或检查范围使用正则表达式。

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

如果要检查数字,请使用is_numeric强制执行整数或转换为特定类型,这样可以防止人们尝试发送字符串。

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

如果你必须处理HTML,那么你应该考虑像 PHP输入过滤器HTML净化器 。 HTML Purifier还将验证HTML的一致性。我不确定输入过滤器是否仍在开发中。两者都允许您定义一组可以使用的标记以及允许的属性。

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

2
Dave

我发现使用此功能有助于消除许多可能的xss攻击: http://www.codebelay.com/killxss.phps

2
barce

“魔术引号”对于一些最糟糕的XSS漏洞是一种姑息性的补救措施,它通过逃避输入中的所有内容起作用,这是设计错误的。人们想要使用它的唯一情况是,你绝对必须使用已知的关于XSS的已知PHP应用程序。 (在这种情况下,即使使用“魔术引号”,您也会遇到严重问题。)在开发自己的应用程序时,应禁用“魔术引号”并改为遵循XSS安全惯例。

XSS是一个跨站点脚本漏洞,当应用程序在其[X] HTML,CSS,ECMAscript或其他浏览器解析的输出中包含来自外部源(用户输入,从其他网站获取等)的字符串而没有正确转义时,就会发生这种情况,希望特殊字符如小于(在[X] HTML中),单引号或双引号(ECMAscript)将永远不会出现。对它的正确解决方案是始终根据输出语言的规则转义字符串:使用[X] HTML中的实体,ECMAscript中的反斜杠等。

因为很难跟踪不受信任和必须转义的内容,所以总是要逃避所有“文本字符串”,而不是像HTML这样的语言中的“带标记的文本”。一些编程环境通过引入几个不兼容的字符串类型使其变得更容易:“string”(普通文本),“HTML字符串”(HTML标记)等。这样,从“字符串”到“HTML字符串”的直接隐式转换是不可能的,字符串可以成为HTML标记的唯一方法是通过转义函数。

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

2
Alexey Feldgendler

对于大多数站点来说,转义所有用户输入就足够了。还要确保会话ID不会在URL中结束,因此不能从Referer链接中窃取到另一个站点。此外,如果您允许用户提交链接,请确保不允许使用javascript:协议链接;一旦用户点击链接,这些将执行脚本。

2
Konrad Rudolph

所有这些答案都很棒,但从根本上说,XSS的解决方案是停止通过字符串操作生成HTML文档。

对任何应用程序来说,过滤输入总是一个好主意。

使用htmlentities转义输出,并且朋友应该在正确使用时工作,但这相当于通过将字符串与mysql_real_escape_string($ var)连接来创建SQL查询 - 它应该可以工作,但是更少的东西可以验证你的工作可以这么说,与使用参数化查询的方法相比。

长期解决方案应该是应用程序在内部构建页面,可能使用像DOM这样的标准接口,然后使用库(如libxml)来处理到XHTML/HTML /等的序列化。当然,我们距离流行和足够快的人还有很长的路要走,但与此同时我们必须通过字符串操作来构建我们的HTML文档,而且这本身就更具风险。

2
Daniel Papasian
  • 不要相信用户输入
  • 转义所有自由文本输出
  • 不要使用magic_quotes;查看是否存在DBMS特定变体,或使用PDO
  • 考虑尽可能使用仅HTTP的cookie,以避免任何恶意脚本能够劫持会话
1
Rob

您至少应该验证进入数据库的所有数据。并尝试验证离开数据库的所有数据。

mysql_real_escape_string可以防止SQL注入,但XSS比较棘手。你应该尽可能preg_match,stip_tags或htmlentities!

1
Abeon

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

1
Night Owl

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

这不是解决方案,只是墙上的另一块砖

1
basszero

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

0
Darren22

使用现有的用户输入清理库来清除 all user-input。除非你给它一个 lot 的努力,否则自己实现它将永远不会有效。

0
dbr