浅析php7.4中自定义对象序列化机制和全新拓展方式FFI的漏洞问题
Posted wanghaoran-s1mple
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析php7.4中自定义对象序列化机制和全新拓展方式FFI的漏洞问题相关的知识,希望对你有一定的参考价值。
浅析php7.4中自定义对象序列化机制和全新拓展方式FFI的漏洞问题
今天有碰到一个很好的题目;也遇到了很多的小坑,就先来看一下题吧;题目源码如下;
看到直接是可以命令执行了;我们system("ls");一下;发现被ban了;打开phpinfo看看,如下的效果;
发现是7.4的;并且看到了有很多函数被禁止了;这里我们发现命令执行的函数无一幸免;我们的目录也被锁定,无法打开其他目录下的文件;然后利用没有被ban的方法来看看;发现有个preload.php的文件,我们读取,发现源码;这里看到很熟悉,想到php反序列化漏洞;但是这里我们并没有发现什么可以传入参数的地方,也无法执行什么序列化;
补充知识点
基于php7.4的新的自定义对象序列化机制;https://wiki.php.net/rfc/custom_object_serialization(引入了__serialize
和__unserialize
两种方法);
从这个文档里可以进行研究,这里我简单的介绍一下php—Serializable接口;这个接口的效果就是:实现此接口的类将不再支持 __sleep()
和 __wakeup()
。不论何时,只要有实例需要被序列化,serialize 方法都将被调用。它将不会调用 __destruct()
或有其他影响,除非程序化地调用此方法。当数据被反序列化时,类将被感知并且调用合适的 unserialize() 方法而不是调用 __construct()。
简单的来理解就是实现的效果和我们之前的pop链利用差不多,我们也是可以构造出exp来进行攻击的;我们构造exp时赋的值可以对原本的数值进行所谓的覆盖;从而利用我们自定义的值;但是这里的新的自定义对象序列化机制就可以将其理解成代码的分块执行;差不多是这种感觉;在实例化的时候,就只是执行了魔法__construct方法;然后调用unserialize时,也是执行了相应的模块,因为这里我们也是可以控制实例化时的参数的,所以问题不大,也可以自己定义一些东西让代码来进行反序列化从而调用;
解释FFI拓展C库进行利用
FFI扩展已经通过RFC,正式成为php7.4的核心拓展;这里FFI;即是外部函数接口,是指在一种语言中引用另外一种语言的技术;这里的FFI就是在php代码中调用C代码的技术;可以让我们很轻易的调用C写的各种库;看看文档;
现有大量的PHP扩展是对一些已有的C库的包装,比如常用的mysqli, curl, gettext等;这里我们看到环境已经ban掉了很多函数,这里我们就需要思考能否引入C库,然后进行调用C库;https://wiki.php.net/rfc/preload这篇文章的结尾i解释道FFI扩展是一个很危险的拓展,但是这道题里明显开启了FFI拓展,(可在PHPINFO中看到);
攻击题目
看到这里我们就可以利用php代码构造pop链进行攻击题目了;贴出我的exp
解释
这里删除了__serialize
和__unserialize
方法,避免其在序列化和反序列化的时候执行;这里我们引入C库;这里不设置FFI::cdef的第二个参数也是可以使用的;可能是因为系统在调用system函数的时候会自动从系统默认的共享库中进行搜索看看函数时候定义,所以这里我们也没必要声明了;然后我们进行反序列化,因为类的实例执行了反序列化,所以这里将调用了unserialize方法,这个方法下面有个run方法,将ret赋值,然后我们可以直接调用C中的system方法,进行读取;然后通过__serialize方法中的return返回回来;因为这里带不出数据,所以我么打到vps上就好;
这里有师傅可能会很疑惑,感觉可以eval,为什么不来直接调用FFI进行C库的引入直接执行命令呢;这里我解释解释,我们在phpinfo中可以看到如下的几行内容;
这里看到确实是开启了FFI ;但是这里我猜测是因为题目里的暗示,这里有个preload.php;也是暗示了是preload;我们看看文档;文档告诉我如果开启了ffi.enable=preload;那就只有在opcache.preload的脚本中的函数才能调用FFI,而用户写的函数是没有办法直接调用的。我们翻看phpinfo;
发现这个脚本的位置就是preload.php看来猜测是正确的;这也就是我们为什么没有办法直接调用了,而是需要pop链的利用;
以上是关于浅析php7.4中自定义对象序列化机制和全新拓展方式FFI的漏洞问题的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET WEB API 中自定义对象的序列化 [重复]
浅析在QtWidget中自定义Model(beginInsertRows()和endInsertRows()是空架子,类似于一种信号,用来通知底层)