ThinkPHP5.1.x RCE分析

修复

造成这个漏洞的主要原因为1.以反斜线\开始时直接将其作为类的命名空间路径。2.thinkphp命名空间自动加载类的特性。官方采的修复方式修复:对控制器的命名规则进行正则检测:

thinkphp/library/think/route/dispatch/Url.php 63行

1
2
3
    if ($controller && !preg_match('/^[A-Za-z][\w|\.]*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}

漏洞和分析

环境搭建

1
php.exe composer.phar create-project topthink/think=5.1.20 tp  --prefer-dist

POC

1
http://127.0.0.1/tp5.1.20/public/index.php?s=index/think\App/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
1
http://127.0.0.1/tp5.1.20/public/index.php?s=index/think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

thinkphp/library/think/APP.php 402 路由检测

F7进入 routeCheck()

thinkphp/library/think/APP.php 598 获取应用调度信息

进入path()

thinkphp/library/think/Request.php 716

在没有定义路由的情况下典型的URL访问规则(PATHINFO模式)是:http://serverName/index.php(或者其它应用入口文件)/模块/控制器/操作/[参数名/参数值...]

进入pathinfo()

thinkphp/library/think/Request.php 680 根据不同的请求方式获取当前URL的pathinfo信息

thinkphp/library/think/APP.php 604 对路由进行解析,返回一个dispatch对象

thinkphp/library/think/route/dispath/URL.php 23 解析默认的URL规则

进入parseUrl()

thinkphp/library/think/route/dispath/URL.php 48

进入parseUrlPath()

thinkphp/library/think/route/rule.php 960 对path进行/分割,分割成模块/控制器/操作方法

进入init()

thinkphp/library/think/route/dispatch/Module.php 37 多模块部署 满足该模块不是deny模块,且存在这个模块(index),则将$available = true;

thinkphp/library/think/route/dispatch/Module.php 58 模块初始化

thinkphp/library/think/APP.php 406 对路由进行调度

thinkphp/library/think/APP.php 431

thinkphp/library/think/APP.php 431

进入add(),注册中间件

thinkphp/library/think/APP.php 435 调度中间件

进入dispath()

进入resolve()

就会调用之前App类中的闭包函数。这里会调用Dispatch类中的run()方法

thinkphp/library/think/route 168

进入 exec()

thinkphp/library/route/dispatch 92 实例化控制类即\think\container

进入controller()

进入parseModuleAndClass()

这里一旦控制器是以\开头则会直接将其作为类的命名空间路径,这也是导致这个漏洞的主要原因

接着就会判断其是否存在并加载这个类,也就是container

进入make()

thinkphp/library/think/container.php 278

进入invokeFunction()

进行反射实例化

thinkphp/library/think/route/dispatch/Module.php 132 利用反射机制调用类方法,从而进行代码执行

最终调用了thinkphp/library/think/Container.phpcall_user_func_array()执行任意函数调用

本文标题:ThinkPHP5.1.x RCE分析

文章作者:MuseLJH

发布时间:2019年07月06日 - 11:25

最后更新:2020年02月19日 - 16:51

原始链接:https://museljh.github.io/2019/07/06/ThinkPHP5.1.x RCE分析/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------END-------------
0%