用户
搜索
  • TA的每日心情
    郁闷
    2018-4-12 15:57
  • 签到天数: 93 天

    连续签到: 1 天

    [LV.6]常住居民II

    i春秋作家

    wing

    Rank: 7Rank: 7Rank: 7

    31

    主题

    158

    帖子

    1265

    魔法币
    收听
    0
    粉丝
    12
    注册时间
    2016-9-29

    i春秋签约作者

    发表于 2019-1-15 18:55:19 05262

    前言

    上次出的洞是接近元旦吧,好像刚从南京回学校,要准备烦人的期末,没心思分析,前天我刚考完,今天刚爆的洞洞貌似。然后自己跟着调试了一下。

    漏洞细节

    这是复现图

    前提是要在index.php中禁止报错,其实在生产环境中,开发也会这么做。

    漏洞点在\thinkphp\library\think\Request.php中的method函数:

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

    如图,我已经在这里下断点了

    var_method  是预定义的

    $this->{$method} = $_POST;

    这里有一个变量覆盖。

    array (size=3)
      'c' => string 'system' (length=6)
      'f' => string 'whoami' (length=6)
      '_method' => string 'filter' (length=6)

    这里为什么要覆盖filter呢?

    是为了最后这里,在call_user_func()   这里执行。

    说明
    
    mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $... ]] )
    第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

    得到结果。
    官方的修复代码:

    
                return $this->server('REQUEST_METHOD') ?: 'GET';
            } elseif (!$this->method) {
                if (isset($_POST[$this->config['var_method']])) {
                    $this->method    = strtoupper($_POST[$this->config['var_method']]);
                    $method          = strtolower($this->method);
                    $this->{$method} = $_POST;
                    $method = strtolower($_POST[$this->config['var_method']]);
                    if (in_array($method, ['get', 'post', 'put', 'patch', 'delete'])) {
                        $this->method    = strtoupper($method);
                        $this->{$method} = $_POST;
                    } else {
                        $this->method = 'POST';
                    }
                    unset($_POST[$this->config['var_method']]);
                } elseif ($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')) {
                    $this->method = strtoupper($this->server('HTTP_X_HTTP_METHOD_OVERRIDE'));
                } else {
    @@ -1320,7 +1325,8 @@ public function header($name = '', $default = null)
         * @param array $data 数据源
         * home.php?mod=space&uid=126298 void
         */
        public function arrayReset(array &$data) {
        public function arrayReset(array &$data)
        {
            foreach ($data as &$value) {
                if (is_array($value)) {
                    $this->arrayReset($value);

    只允许五种方法,保证变量在可控范围内。

    总结

    大佬们真牛逼!!!

    evilwing.me——余生,请多指教。
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册