代码之家  ›  专栏  ›  技术社区  ›  Rik Heywood

避免PHP站点中XSS攻击的最佳实践是什么

  •  64
  • Rik Heywood  · 技术社区  · 16 年前

    我对PHP进行了配置,这样就可以打开magic引号,关闭register globals。

    我尽我所能,总是调用htmlEntities()来处理从用户输入派生的任何输出。

    我偶尔也会搜索我的数据库中附加在XSS中使用的常见事物,例如…

    <script
    

    我还应该做什么?我如何确保我要做的事情是 总是 完成。

    20 回复  |  直到 8 年前
        1
  •  58
  •   Michał Niedźwiedzki    16 年前

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

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

    • 未修改存储用户输入(输入上没有HTML转义,只有通过PDO准备的语句进行的数据库感知转义)
    • 根据所使用的输出格式(例如,HTML和JSON需要不同的转义规则),在输出上转义
        2
  •  18
  •   Jilles    16 年前

    我认为一个人不应该在输入时逃避任何东西,只在输出时。因为(大多数情况下)你不能假定你知道数据的去向。例如,如果您有一个表单接受稍后出现在您发送的电子邮件中的数据,那么您需要不同的转义(否则恶意用户可能会重写您的电子邮件头)。

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

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

    做空:

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

    如果在输入层转义数据(或需要再次反转义数据等),则会发生esp 3。

    附言:我会附和不使用魔法语录的建议,这些都是纯粹的邪恶!

        3
  •  12
  •   Christian Studer delphist    16 年前

    有很多方法可以实现XSS(请参见 http://ha.ckers.org/xss.html )很难抓住。

    我个人将此委托给我正在使用的当前框架(例如代码点火器)。虽然不完美,但它可能比我手工制作的程序捕捉更多。

        4
  •  10
  •   Matt Farina    16 年前

    这是个很好的问题。

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

    当你去呈现你的数据时,过滤掉不应该存在的东西。例如,如果没有理由让javascript出现在那里,请搜索并删除它。一个简单的方法就是使用 strip_tags 函数,只显示您允许的HTML标记。

    接下来,获取您拥有的并将其思想传递给HTMLEntities或HTMLSpecialChars,以将其中的内容更改为ASCII字符。这样做是基于上下文和你想得到什么。

    我也建议关闭魔法引语。它已经从php 6中删除,并且被认为是使用它的坏做法。细节在 http://us3.php.net/magic_quotes

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

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

        5
  •  7
  •   Mason    16 年前

    里克写道:

    我尽我所能,总是调用htmlEntities()来处理从用户输入派生的任何输出。

    看乔尔的文章 Making Code Look Wrong 关于这个的帮助

        6
  •  4
  •   Kornel    14 年前

    我依靠 PHPTAL 为此。

    与smarty和plain php不同,默认情况下它会忽略所有输出。这对安全性来说是一个巨大的胜利,因为如果你忘记了,你的网站就不会变得容易访问。 htmlspecialchars() |escape 某处。

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

        7
  •  4
  •   user319490    14 年前

    模板库。 或者至少,模板库应该这样做。 防止XSS 全部的 应对输出进行编码。这不是主应用程序/控制逻辑的任务,它应该只由输出方法处理。

    如果在代码中加入htmlEntities()thorughout,则总体设计是错误的。正如你所建议的,你可能会错过一两个地点。 这就是为什么唯一的解决方案是严格的HTML编码 &何时 输出变量被写入HTML/XML流。

    不幸的是,大多数PHP模板库只添加自己的模板语法,但不关心输出编码、本地化、HTML验证或任何重要的内容。也许其他人知道一个合适的PHP模板库?

        8
  •  2
  •   Konrad Rudolph    16 年前

    对于大多数站点来说,转义所有用户输入就足够了。同时确保会话ID不会出现在URL中,这样就不会从 Referer 链接到其他网站。此外,如果允许用户提交链接,请确保不 javascript: 协议链接是允许的;一旦用户单击链接,这些链接就会执行一个脚本。

        9
  •  2
  •   Niyaz    16 年前

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

    阅读更多: Sanitizing user data: How and where to do it

        10
  •  2
  •   Dave    16 年前

    就我个人而言,我会禁用魔幻语录。在php5+中,它在默认情况下是禁用的,最好像根本不存在一样进行编码,因为它不会逃避所有的东西,它将从php6中删除。

    接下来,根据您筛选的用户数据类型,将指定下一步要执行的操作,例如,如果它只是文本(例如名称),则 strip_tags(trim(stripslashes())); 它或检查范围使用正则表达式。

    如果需要某个范围的值,请创建一个有效值数组,并只允许这些值通过( in_array($userData, array(...)) )

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

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

    如果必须处理HTML,则应考虑 PHP Input Filter HTML Purifier . HTML净化器还将验证HTML的一致性。我不确定输入滤波器是否还在开发中。两者都允许您定义一组可以使用的标记以及允许哪些属性。

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

        11
  •  2
  •   Daniel Papasian    16 年前

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

    过滤输入对于任何应用程序都是一个好主意。

    使用htmlentities()和friends转义输出应该可以在正确使用的情况下工作,但这相当于通过将字符串与mysql_real_escape_string($var)连接来创建SQL查询,它应该可以工作,但与使用参数化查询之类的方法相比,验证您的工作的东西更少。

    长期的解决方案应该是让应用程序在内部构造页面,可能使用标准接口(如DOM),然后使用库(如libxml)来处理对xhtml/html/等的序列化。当然,我们离流行和足够快还有很长的路要走,但同时我们必须构建HTML文档它通过字符串操作,这是固有的更高风险。

        12
  •  2
  •   barce    16 年前

    我发现使用此函数有助于排除许多可能的XSS攻击: http://www.codebelay.com/killxss.phps

        13
  •  2
  •   Alexey Feldgendler    14 年前

    对于一些最糟糕的XSS缺陷,MagicQuotes是一种姑息性的补救方法,这些缺陷可以通过在输入上转义所有内容来工作,而设计上却有问题。唯一需要使用它的情况是,您必须使用已知不小心编写的关于XSS的现有PHP应用程序。(在这种情况下,即使使用magic-quotes,您也会遇到严重的问题。)在开发自己的应用程序时,您应该禁用magic-quotes并改为遵循XSS安全实践。

    XSS是一个跨站点脚本漏洞,当应用程序在其[x]html、css、ecmascript或其他浏览器分析的输出中包含来自外部源(用户输入、从其他网站获取等)的字符串,而没有正确的转义,希望小于(x]html中)、单引号或双引号(ecmascript)等特殊字符不会出现。ER出现。正确的解决方案是始终根据输出语言的规则转义字符串:使用[X]HTML中的实体、ECMAScript中的反斜杠等。

    因为很难跟踪不受信任的内容并必须进行转义,所以最好始终转义文本字符串,而不是HTML等语言中带有标记的文本。一些编程环境通过引入几个不兼容的字符串类型来简化工作:字符串(普通文本)、HTML字符串(HTML标记)等等。这样,从字符串到HTML字符串的直接隐式转换是不可能的,而字符串成为HTML标记的唯一方法是通过转义函数传递它。

    注册全局变量,尽管禁用它绝对是一个好主意,但它处理的问题与XSS完全不同。

        14
  •  1
  •   basszero    16 年前

    使您使用任何会话cookie(或所有cookie),您只使用httponly。在这种情况下,大多数浏览器都会将cookie值隐藏在javascript中。用户仍然可以手动复制cookie,但这有助于阻止直接脚本访问。stackoverflow在beta期间有这个问题。

    这不是解决办法,只是墙上的另一块砖

        15
  •  1
  •   Rob    16 年前
    • 不信任用户输入
    • 退出所有自由文本输出
    • 不要使用magic_引号;看看是否有DBMS特定的变体,或者使用pdo
    • 考虑尽可能使用HTTP专用cookie,以避免任何恶意脚本能够劫持会话。
        16
  •  1
  •   Abeon    14 年前

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

    mysql_real_escape_string很好地防止了SQL注入,但xss更为棘手。 在可能的情况下,您应该预匹配、stip标记或htmlentities!

        17
  •  1
  •   Night Owl    13 年前

    当前防止PHP应用程序中XSS的最佳方法是HTML净化器(http://html净化器.org/)。它的一个小缺点是它是一个相当大的库,最好与类似apc的op代码缓存一起使用。您可以在任何将不受信任的内容输出到屏幕的地方使用此选项。HTMLEntities、HTMLSpecialChars、filter_input、filter_var、strip_tags等更为深入。

        18
  •  0
  •   dbr    16 年前

    使用现有的用户输入清理库进行清理 全部的 用户输入。除非你把 许多 投入其中的努力,你自己去实现它也不会奏效。

        19
  •  0
  •   Darren22    16 年前

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

        20
  •  -1
  •   Mr Lister Bidstrup    8 年前

    很难在一个不会导致错误警报的站点上实现彻底的SQL注入/XSS注入预防。在CMS中,最终用户可能希望使用 <script> <object> 链接到其他网站上的项目。

    我建议所有用户安装带有noscript的firefox;-)