内容简介:1月11日,公告:补丁:
0x01 概述
1月11日, ThinkPHP
官方发布新版本5.0.24,修复了一个安全问题,该问题可能导致 GetShell
,这是 ThinkPHP
近期的第二个高危漏洞,两个漏洞均是无需登录即可远程触发,危害极大。
公告: https://blog.thinkphp.cn/910675
补丁: https://github.com/top-think/framework/commit/4a4b5e64fa4c46f851b4004005bff5f3196de003
0x02 影响版本
5.0.x ~ 5.0.23
0x03 环境搭建
选择 5.0.22
版本进行复现分析
0x04 漏洞分析
我们知道可以通过 http://127.0.0.1/public/index.php?s=captcha
的方式通过 s
参数传递具体的路由,具体调用如下
index.php
require __DIR__ . '/../thinkphp/start.php';
start.php
App::run()->send();
跟进 run()
方法
可以看到在进入 self::exec($dispatch, $config)
前, $dispatch
的值是通过 $dispatch = self::routeCheck($request, $config)
设置的,先进入 exec()
方法看一下:
exec()
方法根据 $dispatch
的值选择进入不同的分支,当进入 method
分支时,调用 Request::instance()->param()
方法,跟进 param()
,看到调用了 Request
类的 method()
方法 :
$method = $this->method(true);
其中 method()
方法就是补丁修改的位置,在这个方法中,如果 method
等于 true
,则调用 $this->server()
方法::
在 server()
方法中调用 $this->input
方法:
接着调用了 filterValue()
方法:
而 filterValue()
则调用了 call_user_func()
方法,如果两个参数均可控,则会造成命令执行:
回头看一下 $filter
和 $value
参数从哪里来:
-
$filter
:
$filter = $this->getFilter($filter, $default);
在 getFilter()
中设置了 $filter
值:
$filter = $filter ?: $this->filter;
也即由 $this->filter
决定
-
$value
$value
为第一个参数 $data
,即为传入数组的值,由 $this->server
决定
所以最终的问题就是如何从请求中传入 $this->filter
和 $this->server
这两个值,构造 call_user_func()
的参数触发漏洞。
回到最开始的 run()
方法,其中:
$dispatch = self::routeCheck($request, $config);
$dispatch
的值通过 routeCheck()
方法设置,根据routeCheck()方法:
调用了 check()
方法:
check()
方法中根据不同的 $rules
值返回不同的结果,而 $rules
的值由 $method
决定, $method
则由 $request->method()
返回值取小写获得,所以再次回到 $request->method()
方法,这次没有参数
如果 $method
不等于 true
,则会取配置选项 var_method
,该值为 _method
然后调用 $this->{$this->method}($_POST);
语句,此时假设我们控制了 $method
的值,也就意味着可以调用 Request
类的任意方法,而当调用构造方法 __construct()
时,就可以覆盖 Request
类的任意成员变量,也就是上面分析的 $this->filter
和 $this->server
两个值,同时也可以覆盖 $this->method
,直接指定了 check()
方法中的 $method
值。
0x05 构造PoC
首先要主动触发 Request
类的构造函数,通过参数 _method=__construct
传入,进入到 __construct
方法,该方法把参数遍历并设置值:
所以我们可以传入 filter=system
来设置 $this->filter
的值
此处 filter
不是数组也可以,因为在 getFilter()
中虽然对 filter
是字符串的情况进行了按 ,
分割,但是传入一个值的情况下不影响最终的返回值
再看 $this->server
,在调用 $this->server('REQUEST_METHOD')
时指定了键值,所以通过传入 server
数组即可
server[REQUEST_METHOD]=id
然后我们注意到上面 check()
方法,
$rules = isset(self::$rules[$method]) ? self::$rules[$method] : [];
它的返回值由 $rules
决定,而 $rules
的值取决于键值 $method
,当我们指定 $method
为 get
时,可以正确获取到路由信息,从而通过 checkRoute()
检查,此时我们通过指定 method=get
覆盖 $this->method
的值即可
最终的 PoC
:
_method=__construct&filter=system&method=get&server[REQUEST_METHOD]=id
调用栈如下图所示
0x06 总结
这个漏洞本质上是一个覆盖漏洞,通过 _method
覆盖了配置文件的 _method
,导致可以访问 Request
类的任意函数,而在 Request
的构造函数中又创建了恶意的成员变量,导致后面的命令执行,整个漏洞利用可以说是非常巧妙了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析
- 【漏洞分析】CouchDB漏洞(CVE–2017–12635, CVE–2017–12636)分析
- 【漏洞分析】lighttpd域处理拒绝服务漏洞环境从复现到分析
- 漏洞分析:对CVE-2018-8587(Microsoft Outlook)漏洞的深入分析
- 路由器漏洞挖掘之 DIR-815 栈溢出漏洞分析
- Weblogic IIOP反序列化漏洞(CVE-2020-2551) 漏洞分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Visual C++网络通信协议分析与应用实现
汪晓平、钟军 / 人民邮电出版社 / 2003-2-1 / 60.00元
本书介绍了如何利用Visual一起来看看 《Visual C++网络通信协议分析与应用实现》 这本书的介绍吧!