laravel5.7(CVE-2019-9081)
漏洞分析
漏洞起始点位于vendor\laravel\framework\src\Illuminate\Foundation\Testing\PendingCommand.php中 PendingCommand类的__destruct方法
在220行调用了run方法,跟进该方法
首先代码段执行到 $this->mockConsoleOutput(); 跟进去看一下
我们的目的是走出 mockConsoleOutput函数,不影响正常执行代码即可,那么需要继续跟进162行的createABufferedOutputMock函数
我们需要正常执行195行的foreach函数,在这里$this->test我们可以控制,我们需要找到一个存在 expectedOutput属性的类进行进一步的操作,但是这样的类虽然存在,但是无法被框架自动加载,在这里我们可以使用__get魔术方法,这里选择vendor\laravel\framework\src\Illuminate\Auth\GenericUser.php中GenericUser类的__get方法
这里 $this->attributes我们可以控制,这样我们可以控制$this->test为GenericUser的一个对象,进而可以走过该处foreach的代码段,接着回到mockConsoleOutput方法,在165行同样存在着类似的foreach代码段,我们可以使用相同的方法正常走过该段代码,接着回到run方法,来到该段代码
1 | $exitCode = $this->app[Kernel::class]->call($this->command, $this->parameters); |
调试发现Kernel::class的值为Illuminate\Contracts\Console\Kernel
继续跟踪调试,来到container类中的resolve方法,存在着下面的代码
跟进 getConcrete,存在如下代码段
在这里我们可以寻找一个继承了Container的类来控制 $this->bindings的值,这里选择了vendor\laravel\framework\src\Illuminate\Foundation\Application.php中的Application类,可以控制$this->bindings为如下值
1 | array('Illuminate\Contracts\Console\Kernel'=>array('concrete'=>'Illuminate\Foundation\Application')) |
回到 resolve方法,会走到如下代码段
跟进isBuildable
很显然会走进上面的else分支调用make方法,跟进后发现代码段其实是重新做了一次上面的操作,重新调用了 getConcrete方法,最后进行Illuminate\Foundation\Application的build操作,最后
$this->app[Kernel::class]返回的是Application的一个对象,接着会调用该对象的call方法,但是该对象中不存在call方法,进而会调用其父类Container中的call方法
跟进 BoundMethod::call
该处调用了 call_user_func_array,我们知道该方法是可以执行代码的,调试后发现该处可以控制为如下的利用代码
1 | call_user_func_array('system',array('whoami')) |
payload编写
1 |
|
laravel5.8(一)
漏洞分析
起始点位于、vendor\laravel\framework\src\Illuminate\Broadcasting\PendingBroadcast.php中的__destruct方法
该处的$this->events可控,我们可以利用该处调用位于 vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php中的dispatch方法
如果满足了if条件,代码会调用 dispatchToQueue方法,跟进该方法
在150行处调用了 call_user_func,并且两个参数也是可控的,在该处我们可以达到执行命令的目的,那么回过来看一下如何满足前面的if条件
$this->queueResolver需要存在,并且在call_user_func中作为第一个参数,我们直接控制要执行的函数名即可,接着是$this->commandShouldBeQueued($command),跟进去看一下
ShouldQueue是一个接口,我们需要将$command设置为一个ShouldQueue的实现类,这里选用vendor\laravel\framework\src\Illuminate\Broadcasting\BroadcastEvent.php中的类,同时为了满足call_user_func的第二个参数,我们需要在该类中设置一个connection属性。来作为调用函数的参数
最后来梳理下利用链
1 | (PendingBroadcast)->__distruct() |
payload编写
1 |
|