函数调用链:
漏洞成因:
这个漏洞是有利用条件的,前提是当前的ThinkPHP开启了”多语言”中间件功能。中间件是ThinkPHP中的一个功能,可以用来对请求数据进行过滤处理,请求拦截,自动分发处理等等。很多额外的非核心业务流程的处理都可以交给中间件执行。ThinkPHP中的中间件分为系统中间件和应用中间件,系统中间件为框架自带的内置的中间件。问题出在多语言加载的中间件中(系统中间件),在默认情况下系统中间件都是关闭的,需要手动开启。该中间件功能开启后会根据具体需求自动加载语言包,系统会自动侦测多语言进行自动切换。该中间件在获取用户键入参数时,没有对lang参数进行严格过滤,从而导致了文件包含。
中间件详细介绍—https://www.php.cn/phpkj/thinkphp/438708.html
本地复现:
Version:6.0.12
前提条件:
开启多语言中间件功能
0x01:
首先在public文件夹下新建test.php文件,用于充当被包含文件测试漏洞是否存在
0x02:
进到\vendor\topthink\framework\src\think\middleware\LoadLangPack.php文件,中间件在开启的情况下会默认调用其中的handle()方法,在handel方法中调用了detect方法。
跟进detect方法,langSet变量默认情况下为空,再向下会进入第一个分支获取url中的lang参数,config变量在该中间件类的构造方法中进行了获取,在配置文件中其”detect_var”键的值为”lang”,所以这里获取到了url中的lang参数,并且没有对该参数做任何过滤,直接赋值给了LangSet变量。继续向下,进入分支,”allow_lang_list”默认为空,进入第一个分支LangSet直接被赋值给了Range并返回。
0x03:
所以detect方法返回值是可控的lang参数,回到handle方法,再向下调用了defaultLangSet()该方法用于获取当前默认语言默认语言值为”zh-cn”,与传入的可控变量langSet参数进行字符串比较,如果不一样则调用switchLangSet()方法, langSet作为参数进行传递。
0x04:
跟进switchLangSet方法,该方法首先判断参数是否为空,参数不为空继续向下执行。调用load方法,load方法首先获取tp项目路径。再将可控变量$langset直接与其绝对路径进行拼接。最终得到字符串”项目路径+\vendor\topthink\framework\src\lang../../../../public/test.php”,将其作为数组成员传递进load方法。
0x05:
跟进load方法, 到达漏洞触发点,load方法对传入数组进行遍历取值,首先判断该文件是否存在,存在则调用parse()方法,parse方法中判断被包含文件后缀如果为.php结尾则直接使用Include进行包含。
昶之琴![资深玩家 徽章-资深玩家-NGC660 安全实验室](http://ngc660.cn/wp-content/themes/zibll/img/thumbnail-null.svg)
2年前0
我以为只要提交就行了好想告诉你![备受喜爱 徽章-备受喜爱-NGC660 安全实验室](http://ngc660.cn/wp-content/themes/zibll/img/thumbnail-null.svg)
2年前0
花巨资看一下