今年三月份的时候,乌云上面刷了很多SSRF漏洞,很多大厂商都有中招。
我也对一些业务进行了漏洞检测,主要修复的办法就是白名单,对于用户传入的url地址,在需要发起请求的时候,进行白名单过滤,防火墙限制等等。
这里就不讨论SSRF问题了,而是做代码检查时发现白名单代码,写的很有意思,很有迷惑性,在这里分享出来。
test.php代码如下:
$url = $_GET['url'];
$info = parse_url($url);
//假设www.site.com为白名单网站
if($info['host'] != 'www.site.com')
{
echo '目标网址不合法';
exit;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
上面这段代码我们知道,主要是进行网址过滤,如果用户输入的网址不是公司的网址,则服务器不会发起请求。
这段代码的目的是,防止用户输入其它恶意数据,造成攻击,比如:
http://www.site.com/test.php?url=http://10.0.0.16 --攻击者尝试内网漫游
http://www.site.com/test.php?url=http://www.hack.com --攻击者引导服务器访问不合法网址
不过这样处理完,上面的代码就安全了么?
新人写代码往往对一些函数并不是了解很深入,这段代码忽视了两个问题:
1. parse_url原理是什么?
parse_url只是负责字符串解析,它不保证你的协议真伪,这里我们不用http协议,而使用一个根本不存在的协议abc测试:
输出结果为:
array(3) { ["scheme"]=> string(3) "abc" ["host"]=> string(13) "www.baidu.com" ["path"]=> string(11) "/test" }
2. curl支持哪些协议?
curl是基于libcurl实现的,支持的协议非常多。
libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password authentication, file transfer resume, http proxy tunneling and more
那么问题来了,我们回到最开始那个代码,我们可以发现存在两处问题:
1. 白名单只是检测了host,而没有检测协议。
2. curl除了支持http协议,还支持file协议。
直接上攻击测试例子:
http://www.site.com/test.php?url=file://www.site.com/etc/passwd
php curl识别出来这是个file协议,他会忽略www.site.com,而是直接读取文件/etc/passwd。
网页乖乖的输出了服务器/etc/passwd的内容,危险无处不在。。。
总结:
不要使用parse_url进行白名单检测,不要忽略协议项,直接字符串正则强匹配。
Leave a Reply