解决php中跨站点脚本XSS的最佳方法/做法?

问题描述

我有一个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。

解决方法

最好的方法是使用HTMLPruifier之类的成熟且受信任的库来清理来自不受信任源的任何内容。仅仅运行strip_tags并不能减少它,那里有很多创造性的,隐蔽的XSS攻击。我建议看一下OWASP recommendations来减轻XSS。值得花些时间小心这种事情,并在开发过程中实际测试漏洞。

如果您是新手,我认为也有必要研究一些白帽子捕获的标志式信息安全培训(有大量可用资源),以便您了解这类攻击的工作方式在现实世界。看到他们有多聪明,真是令人大开眼界。

,

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

通常,htmlspecialchars()就足够了。如果要允许某些标签,则应使用Rob Ruchte建议的HTMLPurifier库。

,

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

,

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

这里,建议对&<>'"/的特殊字符进行编码。除了严格不需要编码的正斜杠外,这就是函数htmlspecialcharshtmlentities的作用。

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

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