Dragon
adminAdmin  2019-01-15 10:07 来源:lsh4ck's Blog 隐藏边栏 |   1 条评论  38 
文章评分 0 次,平均分 0.0

本文主要以官网下载的5.0.23 完整版(thinkphp_5.0.23_with_extend.zip)为例分析。

Thinkphp 处理请求的关键类为 Request(thinkphp/library/think/Request.php)

该类可以实现对 HTTP 请求的一些设置。

其中成员函数 method 用来获取当前请求类型,其定义如下:

该函数主要在其他成员函数(例如 isGet、isPost、isPut 等)中被用来做请求类型判断。

thinkphp 支持配置“表单伪装变量”,默认情况下该变量值为 _method。

因此在 method()中,可以通过“表单伪装变量”进行变量覆盖实现对该类任意函数的调用,并且$_POST 作为函数的参数传入。

Request 类的构造函数定义如下:

构造函数中,主要对$option 数组进行遍历,当$option 的键名为该类属性时,则将该类同名的属性赋值为$options 中该键的对应值。

因此可以构造请求如下,来实现对 Request 类属性值的覆盖,例如覆盖 filter 属性。filter 属性保存了用于全局过滤的函数。

因此在 thinkphp 5.0.10 中可以通过构造如下请求实现代码执行:

在官网最新下载的 5.0.23 完整版中,在 App 类(thinkphp/library/think/App.php)中 module 方法增加了设置 filter 参数值的代码,用于初始化 filter。因此通过上述请求设置的 filter 参数值会被重新覆盖为空导致无法利用。

在 5.0.23 的 Request 类中,存在 param 成员函数用于获取当前请求的参数。其中也有调用 method()函数,并且传入参数值为 true。param 函数代码实现如下:

当传入的$method === true 时 会执行如下代码

其中 server()实现如下:

由此可见,参数$name 为 REQUEST_METHOD,最终会调用 input 函数。input 函数实现如下。最终会执行到$filter = $this->getFilter($filter,$default); 来解析过滤器。

此时$filter 为‘’,$default 为 null。

继续跟进查看 getFilter 函数的实现:

由于$filter = ‘‘,因此可以执行到红线处,并且最终$filter 会被赋值进$this->filter ,和$default 即 null。因此经过“解析过滤器”的过程,$filter 最终可被添加来自请求中的 filter。之后,代码判断了$data 是否为数组,最终将每个值作为参数,通过 filterValue()函数进行过滤。而$data 即为 server()函数中传入的$this->server ,因此也可通过在调用构造函数时,实现对$this->server 值的覆盖。

filterValue 函数实现如下:

最终会通过 call_user_func 来实现代码执行。此处原理同刚刚爆出的 THINKPHP 5 通过控制 controller 值实现反射调用指定类来远程代码执行漏洞原理一致,不再过多分析。因此只需要找到自动触发调用 param()函数的地方即可。

其中在 App 类中的 run()函数中,如果开启了 debug 模式,会实现日志的记录,其中有调用$request->param()。

因此在 debug 模式下,发送如下请求可实现代码执行:

例如 touch /tmp/xxxx

继续分析。可以看到“记录路由和请求信息”之前,还实现了“未设置调度信息则进行 URL 路由检测。”其中通过 routeCheck 函数来设置$dispatch。最终再通过 exec 函数,将$request 和$config 作为参数传入后执行。其中$config 是通过 initCommon 函数调用 init 函数来加载 config 配置文件来实现赋值。$request 即为 Request::instance()。

其中 routeCheck 函数实现如下:

首先会通过加载 config 文件导入“路由配置”。默认配置如下:

然后通过 Route 类的 import 方法加载路由。由于在入口文件 index.php(public/index.php)中加载了 start.php(thinkphp/start.php)

start.php 又加载了 base.php(thinkphp/base.php)

base.php 中实现了注册自动加载

register 函数实现如下:

该函数完成了对 VENDOR 下 class 的加载。其中完成了验证码类路由的加载

因此上面 import 之后,Route 类$rules 值将形如下:

然后代码会执行到“路由检测”的部分即调用 Route::check 的地方,路由检测主要用于根据路由的定义返回不同的 URL 调度。

Route 类 check 函数实现如下:

可以看到该 check 函数中调用了 Request 类的 method 方法。并将函数执行结果转换为小写后保存在$method 变量。由于 Request 类中 method 函数在返回 method 时直接判断了如果存在$this->method 直接返回

因此我们在调用构造函数覆盖变量时,可以直接覆盖 method,这样上面的$method = strtolower($request->method()); 的$method 最终的值就可以被控制了。

回到 check 函数,在设置完$method 后,会根据$method 在 self::$rules 中获取对应$method 的路由信息,并将结果赋值给$rules.

最终函数的 return 将依赖$rules ,因此$method 不同返回也不同。当$method 为 get 时,$rules 将为如下:

由于$item = str_replace('|', '/', $url);   而 $url = str_replace($depr, '|', $url);

而这个$url 最初为该函数的参数,在 App 类 routeCheck 方法中调用

而这个$path = $request->path();

Request 类的 path 方法实现如下:

当 is_null($this->path)时,通过 pathinfo()函数来获取

其中 var_pathino 默认值为 s

因此综上,我们可以通过 URL 中 s 参数来设置 App 类 routeCheck 函数中的$path ,即 Router 类 check 函数中的$url ,最终即能控制 Router 类 check 函数中的$item 从而控制 check 函数真正 return 哪种结果。从而最终影响 App 类 run 方法的$dispath 值即调度信息。由于$dispatch 会作为参数在 exec 中调用。

其中 exec 的实现如下:

exec 会根据$dispatch[‘type’]来决定实际执行的代码。

前面分析可知,我们需要触发 Request 类中 param 函数的调用来完成对 filter 的覆盖。此处显而易见的是,当$dispatch[‘type’]为 controller 和 method 时有直接的调用。当然其他的类型,例如当$dispatch[‘type’]为 function,调用了 invokeFunction,而 invokeFunction 调用了 bindParams 函数,bindParams 函数里存在对 param 函数的调用。总之,我们需要控制请求 url 中 s 的值完成设置不同的$method,最终让 routeCheck 返回我们需要的$dispath 即可。

例如我们控制 url 为 /public/index.php?s=captcha,同时 post body 为 _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls -al 则 check 函数最终会进入

然后 checkRoute 函数,由于 rule 为字符串,

因此最终会进入

然后会进入 parseRule

然后会进入

最后返回$result. 因此最终$dispatch 值为:

因而在传入 exec 函数后,触发 Request 类的 param 方法,最终覆盖 Request 类的 server 变量,接着通过 Request 类的

input 方法,实现任意代码执行。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

admin
Admin 关注:0    粉丝:0
这个人很懒,什么都没写
×

感谢您对admin的支持,么么哒~

支付宝打赏 admin
请扫码随意打赏

打开支付宝扫一扫,即可进行扫码打赏哦

lsh4ck's Blog - Hacking is endless! Focus on network security!

发表评论

表情 贴图 链接 私密 格式 签到

  1. admin
    admin 博主 来自天朝的朋友 谷歌浏览器 Mac OS X 10_14_0

    签到成功!签到时间:2019-01-15 10:08:23,每日打卡,生活更精彩~

切换注册

登录

忘记密码 ?

切换登录

注册

验证码

扫一扫二维码分享