使用双重编码绕过 XSS 清理程序何时以及为何起作用?

信息安全 xss 编码
2021-09-01 06:55:21

我在不同的网站上阅读了有关绕过 XSS 清理程序的不同方法,例如双重编码特殊字符,例如/<>:"',或采用不同的编码方案。

然而,这些网站中的大多数都没有解释为什么这些攻击会起作用以及在哪些情况下起作用。例如,我知道现代浏览器对特殊字符进行 URL 编码,而 cURL 不会这样做;因此您无法使用 cURL(或 Burp 代理)创建 PoC。

有人可以就浏览器如何编码和处理输入数据(POST 和 GET)以及典型的(PHP)Web 应用程序如何处理这些数据给出非常详细的解释吗?根据我在 PHP 方面的一点经验(当我在大学时),我只是在访问参数$_POST["query"],甚至没有考虑编码、安全实践等。

1个回答

让我们看一下这个示例有效载荷 (A),编码一次 (B) 和两次 (C):

A. <script> alert(1) </script>
B. %3Cscript%3E alert(1) %3C%2Fscript%3E
C. %253Cscript%253E alert(1) %253C%252Fscript%253E

当应用程序的不同部分对变量是否被编码做出不同的假设时,双重编码可用于绕过 XSS 过滤器。例如考虑以下易受攻击的代码:

$input = htmlentities($_GET["query"]);
echo urldecode($input);

如果只是单编码(如 B 中),此代码将阻止有效负载。默认情况下,PHP URL 会为您解码您的 GET 变量(将 B 转换为 A),因此<并且>将被传递给htmlentities它来中和它们。但是,如果您改为在 C 中发送,它将被解码为 B 的 URL 将htmlentities不变地通过。由于它在回显之前再次进行了 URL 解码,因此它变成了危险的有效载荷 A。

所以这里的bug就是在XSS过滤器之后还有一层URL解码。当两条线像这样挨着的时候,问题就很明显了。但这两个东西可以在不同的模块中,因此很难检测到。由于很难跟踪哪些字符串是经过 URL 编码的,因此很容易进行额外的解码来确定——毕竟,它通常不会影响未编码的数据。

PHP 手册实际上对此提出了警告:

警告:超全局变量$_GET$_REQUEST已经解码。urldecode()在元素上使用$_GETor$_REQUEST可能会产生意外和危险的结果。

在我看来,手册在这里不够谨慎 - 在过滤 XSS 后解码任何不受信任的数据是危险的,无论它来自哪里。过滤后修改数据时要非常小心!

如需更多阅读,请参阅OWASP