【问题标题】:Best method/practice to solve Cross Site Scripting (XSS) in php?在 php 中解决跨站点脚本 (XSS) 的最佳方法/实践?
【发布时间】:2021-01-10 04:18:53
【问题描述】:

我有一个 php 网页,它使用 URL 参数设置一个变量,然后显示在该页面中。 网址:webaddress.com/page.php?id=someCity

我们获取 $_GET['id'] 并将其分配为变量 ($city),然后在页面上使用该变量以某种动态的方法重构静态文本。

例如:

欢迎来到我们关于Somecity的页面。我们可以帮助您找到与 someCity 相关的产品,因为我们在 Somecity 方面拥有丰富的经验。显然,这可以使用<?php echo $city; ?>

来实现

我的客户被告知他对跨站脚本 (XSS) 漏洞持开放态度。我的研究表明,iFrame 可用于窃取 cookie 并执行恶意操作。推荐的解决方案是使用 PHP 函数 htmlspecialchars() 将字符更改为“HTML 实体”。我不明白这比使用 strip_tags() 简单地删除所有标签更安全。

所以,我同时使用了字符串替换和大写,因为这也是需要的。

 $step1 = str_replace('_', ' ', $_GET['id']); // Remove underline replace with space
 $step2 = strip_tags($step1); // Strip tags
 $step3 = htmlspecialchars($step2); // Change tag characters to HTML entities
 $city = ucwords($step3);

问题:这足以防止 XSS 吗? htmlspecialchars() 是否真的比 strip_tags() 有额外的好处? 我了解基于其他类似问题提交的差异,但想知道每个函数(尤其是 htmlspecialchars() )如何防止 XSS。

【问题讨论】:

  • 其他类似,但没有提供“为什么” htmlspecialchars() 肯定会超过 strip_tags(),这似乎是最正确的。
  • 你确定吗?那里接受的答案确实很好地解释了为什么
  • @WesleySmith 建议的类似问题并不相同,因为它引用了两种情况(或/或)。对该答案和我的案例的仔细审查表明,按顺序使用两者是回答我的问题并希望在类似案例中帮助其他人的最佳方法。

标签: php security xss


【解决方案1】:

这是 OWASP XSS 预防备忘单 (https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html) 中的规则 1。

这里建议对&<>'"/的特殊字符进行编码。除了对编码不是绝对必要的正斜杠之外,这是函数 htmlspecialcharshtmlentities 所做的。

之前运行 strip_tags 的唯一区别是,不是将 < 编码为 < 并将 > 编码为 >,而是将它们与它们之间的其他内容一起从字符串中删除.这不会提供更多安全性,因为字符串 < 在这种情况下与空字符串一样安全。它的缺点是会破坏有效输入,因为<> 可以出现在普通文本中,因此不能始终用作输出编码策略。

另外,对于 HTMLPurifier,这在此处不合适,因为目的是将 HTML 输入转换为 HTML 输出,但您有纯文本输入而不是 HTML。 HTMLPurifier 将保持<b>Somecity</b> 的城市名称不变,并且根本不进行任何编码。这可能是安全的,因为它不能包含脚本,但在这里不允许任何 HTML 格式更改是不合适的,并且应该作为无效输入更早地进行编码或拒绝。

【讨论】:

  • 感谢您的意见。我同意您发布的内容,但在我们正在讨论的情况下,删除所有标签以及任何其他潜在的脚本实体(如图所示)可以解决任何潜在的 XSS 问题。此外,由于范围是简单的文本,建议的两步流程以最有效的方式 (IMO) 解决了问题。
【解决方案2】:

我相信在提供的案例中最好的答案是同时使用这两个函数。首先使用 strip_tags() 剥离所有标签,然后使用 htmlspecialchars() 对剩余的情况进行排序。上面提供了顺序。

【讨论】:

    【解决方案3】:

    strip_tags() 只删除标签,不删除其他特殊字符。另一方面,htmlspecialchars() 将在 HTML 中具有特殊意义的字符视为 HTML 实体。您可以找到更多信息here

    一般来说,htmlspecialchars() 就足够了。如果您想允许某些标签,您应该按照 Rob Ruchte 的建议使用库 HTMLPurifier

    【讨论】:

      【解决方案4】:

      最好的方法是使用像HTMLPruifier 这样成熟且受信任的库来清理来自不受信任来源的任何内容。简单地运行 strip_tags 并不能解决问题,那里有很多创造性和阴险的 XSS 攻击。我建议查看OWASP recommendations 以缓解 XSS。值得花时间注意这类事情并在开发过程中实际测试漏洞。

      如果您是新手,我认为还值得研究一些白帽捕获标志式信息安全培训(有大量免费资源可用),以便了解此类攻击的工作原理在现实世界。看看他们能变得多么聪明,真是令人大开眼界。

      【讨论】:

      • 因为我的情况非常简单(变量需要大量输入字符),也许库是矫枉过正?我可以将输入字符限制为 25max,这对于恶意代码来说似乎不太可能......?无论如何,我会研究你的建议。谢谢
      • 好吧,你问的是最好的方法,而不是最简单的方法,哈哈。
      • HTML Purifier 太过分了,除非您希望用户能够注入 some 而不是 all html 标签。在这种情况下,我会推荐它,但不是为了这个。
      • 我的意思是,我明白了,但问题是最好的方法和最佳实践是什么,最佳实践是将所有内容视为不受信任,即使是存储在数据库中的内容,甚至 (也许尤其是)您的用户正在存储的内容。我已经建立 CMS 20 年了,相信我,你永远不会偏执。 IMO 不过滤进出系统的内容是一种职业弊端。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 2010-09-06
      • 2011-04-08
      • 2015-06-18
      • 1970-01-01
      • 2019-09-14
      • 1970-01-01
      相关资源
      最近更新 更多