1.点击链接,进行代码审计
<?php
highlight_file(__FILE__);
//自定义函数1
function check_inner_ip($url) //判断ip地址是否私有
{
$match_result=preg_match('/^(http|https)?:\/\/.*(\/)?.*$/',$url);
//如果url在正则表达式中,返回1,在第一次匹配后 将会停止搜索
// /为定界符,开头的 ^ 和结尾的 $ 让PHP从字符串开头检查到结尾
if (!$match_result)
{
die('url fomat error');
}
try
{
$url_parse=parse_url($url);
//parse_url()功能是解析一个 URL 并返回一个关联数组
} catch(Exception $e) {
die('url fomat error');
return false;
}
$hostname=$url_parse['host']; //获取域名
$ip=gethostbyname($hostname); //通过域名获取ip地址
$int_ip=ip2long($ip); //ip2long()函数可将IPv4地址(点分IP地址)转换为长整数
return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16; //判断是否是私有地址,是则返回1
}
//自定义函数2
function safe_request_url($url)
{
if (check_inner_ip($url)) //调用自定义函数1,判断url是否是私有地址
{
echo $url.' is inner ip';
} else {
$ch = curl_init();
//PHP的curl库可以简单和有效地去抓网页,curl_init()初始化一个curl会话
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
//curl_setopt()为一个curl设置会话参数
$output = curl_exec($ch);
// 执行一个cURL会话并且获取相关回复
$result_info = curl_getinfo($ch);
//使用curl_getinfo()函数获取CURL请求输出的相关信息
if ($result_info['redirect_url'])
{
safe_request_url($result_info['redirect_url']);
}
curl_close($ch);
var_dump($output);
}
}
$url = $_GET['url'];
if(!empty($url)){
safe_request_url($url); //调用自定义函数2
}
?>
2.构造payload 绕过parse_url()
对于parse_url()返回的数组样式可通过测试得到:
函数1要求host项不能为私有地址,构造url地址:http://@127.0.0.1:80@baidu.com ,这样就可以过函数1的检测,而函数2取到的是127.0.0.1:80,所以就实现了实际curl请求的是构造的127.0.0.1。
3.成功绕过后,访问flag.php 获得flag
http://@127.0.0.1:80@baidu.com/flag.php