给了源码
<?php function check_inner_ip($url) { $match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url); if (!$match_result) { die('url fomat error'); } try { $url_parse=parse_url($url); } catch(Exception $e) { die('url fomat error'); return false; } $hostname=$url_parse['host']; $ip=gethostbyname($hostname); $int_ip=ip2long($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; } function safe_request_url($url) { if (check_inner_ip($url)) { echo $url.' is inner ip'; } else { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 0); $output = curl_exec($ch); $result_info = curl_getinfo($ch); if ($result_info['redirect_url']) { safe_request_url($result_info['redirect_url']); } curl_close($ch); var_dump($output); } } if(isset($_GET['url'])){ $url = $_GET['url']; if(!empty($url)){ safe_request_url($url); } } else{ highlight_file(__FILE__); } // Please visit hint.php locally. ?> |
提示先读本地的hint.php。看看怎么SSRF
check_inner_ip
函数首先对请求进行了内网ip的判断,并不允许内网ip地址的请求
可以发现这里使用了parse_url函数,curl 和 php_url_parse 处理后最终的目标不一样,借用了网络的图
当 php_url_parse 认为 google.com 为目标的同时,curl 认为 evil.com:80 是目标
使用/?url=http://0.0.0.0/hint.php代表本地,访问得到
string(1342) <?php if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){ highlight_file(__FILE__); } if(isset($_POST['file'])){ file_put_contents($_POST['file'],"<?php echo 'redispass is root';exit();".$_POST['file']); } |
得到了redis password
使用https://github.com/xmsec/redis-ssrf
与https://github.com/n0b0dyCN/redis-rogue-server
更改端口设置密码urlencode
buu vps运行下rogue-server
打出去
拿到flag