1.thinkPHP5.0.2完整版
2.需要开启兼容模式(默认开启)
3.该payload无需开启debug模式
ReflectionFunction::invokeArgs
将返回被调用函数的结果
tp中的命名空间用\
以\think\cache\driver\File
类为例,think就是一个根命名空间,其对应的初始命名空间目录就是系统的类库目录(thinkphp/library/think)
,我们可以简单的理解一个根命名空间对应了一个类库包
以?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
为例分析
因为windows会将\
为关键字,导致无法触发命名空间,所以采用?s的方法进行
进入start.php
去think/app.php
的app
类中调用run()
检测URL路由
跟进routeCheck
跟进path
步入pathinfo
可以看到其做了check
检测url中是否具有兼容模式得参数
在application/config.php
中,我们发现var_pathinfo
所以我们获取到了pathinfo
获取到后回到App.php
的routeCheck
中
获得的path
需要进行URL调度
,但是路由调度中存在一些规则返回了false
因为返回了false
,所以进行此步骤
解析URL地址
最终分割开run()
中调用exec
跟进exec。这里就是算正式开始
访问调用了
当type为module
时,调用module()
方法
module用于执行模块
通过路由解析,模块为index
调用init
来初始化模块
初始化步骤跳过
继续往下,获得控制器名"think\app"
,操作名"invokefunction"
随后到think/Loader.php
中Loader类的 controller
下
调用getModuleAndClass()
方法
因为name为think\app
,所以进入if语句
该语句 $module = Request::instance()->module();
表示进入request类先到instance然后到module
注:如果不是\
则通过正常截取/
得到对应的模块和控制器名称,最终得到应用类的类名
getModuleAndClass最终$name为"think\app",$class为"thinkapp"
跳出getModuleAndClass
,继续回到controller
中,$class必须实例化
过,所以进入invokeClass中
进入app的invokeClass中,实例化$class
回到module中,instance为名字为think\App
的类,action为"invokefunction", ReflectionMethod
第一个参数为类,第二个为方法
通过注释我们也可得知,该操作获得操作名为invokeFunction
随后调用invokeMethodblindParams
用于参数绑定(获取请求的变量)function=call_user_func_array&vars[0]=system&vars[1][]=whoam
bindParams将获取到的值存入args
中
返回
随后开始写入日志
在日志写入完成后,return $reflect->invokeArgs(isset($class) ? $class : null, $args);
用到了前面铺垫的知识点,返回被调用函数的结果。$class为类,args为参数。
$reflect为"invokeFunction",将class
类、args
传入//这里一步骤其实就是常规的调用方法
步入到invokeFunction中,反射调用call_user_func_array
函数,args为[‘system’,’whoami’]
因为invokeFunction
需要function
和vars
参数,所以传参的参数名要一致
,否则
回显出结果后,回到之前的exec中。可以看到,命令已经执行完毕exec
return出$data
最终回显到页面上
\
是命名空间的一个标志invokeArgs
会反射调用函数,但前提是要实例化函数,采用了reflectionFunction去实例化。而产生这些的函数在app.php的invokefunction之中而参数可控,所以能命令执行。
1.RCE触发是调用了/thinkphp/library/think/app.php,thinkapp可以过class_check。当我复制出app123.php去打时,发现并未实例化该页面,并不能调用到其中的控制器。那是哪一步实例化的app.php?
学习过程中发现,在application下,只要符合命名空间规范和定义,即可自动实例化
2.payload中传递的参数名改变为什么会有影响?答:我们在跟进中发现一个方法叫blindParams
,其可以将参数名和对应的参数直接对应起来,而后面函数需要用到相关参数时,变量名得一致
3.能否不用兼容模式,直接用其原本的PATHINFO路由方式?答:可以,但是PATHINFO在部分服务器中并不支持,例如笔者的phpstudy起的环境,会将其视为一个完整的文件访问的路径,从而返回404
本文作者:硝基苯
本文链接:https://www.c6sec.com/index.php/archives/482/
最后修改时间:2022-01-30 00:23:15
本站未注明转载的文章均为原创,并采用 CC BY-NC-SA 4.0 授权协议,转载请注明来源,谢谢!