parse_url的小trick

最近几次比赛都用到了parse_url的解析漏洞,所以我就在这里做一波总结

  1. php协议错误
    先放测试代码
    1
    2
    3
    <?php
    $url = $_GET['url'];
    var_dump(parse_url($url));

众所周知,parse_url在url不能被解析的时候就会返回false,然而却没有表明为什么他会爆错。
我们从源码里看一下parse_url

全版本通杀

当一个url没有协议的时候,但是给一个端口url的字符串的时候parse_url就会爆错

1
/pupiles.com:80

这个经测试在windwos下应该是php版本全通杀的(5.2-7.0),linux没测试过

url解析错误

接上发现只要端口后面跟字母还是会解析,比如

1
2
3
/pupiles.com:80a
array (size=1)
'path' => string '/pupiles.com:80a' (length=16)

端口解析错误

php5.5以上

1
//pupiles.com/about:1234

这样的url用parse_url解析后预测的结果是

1
2
3
4
5
6
array(2) {
["host"]=>
string(11) "pupiles.com"
["path"]=>
string(9) "/about:1234"
}

然而实际结果是

1
2
3
4
5
6
7
8
array(3) {
["host"]=>
string(11) "pupiles.com"
["port"]=>
int(1234)
["path"]=>
string(9) "/about:1234"
}

会默认解析出一个portkey

路径解析错误

1
2
3
4
5
6
7
8
9
10
<!--?php
// single slash case
$uri = "/upload?/home/binarycloud/";
$data = parse_url($uri);
print_r($data);
// doubleslash case
$uri = "//upload?/home/binarycloud/";
$data = parse_url($uri);
print_r($data);
?-->

输出结果

1
2
3
4
5
6
7
8
9
10
Array
(
[path] => /upload
[query] => /home/binarycloud/
)
Array
(
[host] => upload?
[path] => /home/binarycloud/
)

端口溢出

在php5.3.13版本以下,当输入如下url

1
http://pupiles:78325

按照正常来说应该会返回false,但是这里会返回

1
2
3
4
5
array(3) { 
["scheme"]=> string(4) "http"
["host"]=> string(7) "pupiles"
["port"]=> int(12789)
}