ThinkPHP是一个开源轻量级PHP框架,其6.0.13及以前版本存在一个文件包含漏洞。简要来讲,在多语言特性开启的条件下,远程攻击者可通过控制传入参数来实现任意PHP文件包含。默认条件下,该漏洞只能包含本地PHP文件;但在开启了register_argc_argv且安装了pcel/pear的环境下,攻击者可通过 get、header、cookie 等传入参数,实现目录穿越包含pearcmd 。最终,通过pearcmd实现写入webshell。该漏洞影响版本为:v6.0.1~v6.0.13、v5.0.x、v5.1.x。本文的分析均使用6.0.12版本。该漏洞要成功被利用需要满足三个条件:
在app/middleware.php中开启多语言功能:在Lang.php 193行处设置断点,发送如下报文:GET /?lang=../../../../../public/index HTTP/1.1
Host: localhost:80
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: think_lang=zh-cn
Connection: close
观察断点处的文件包含代码,file参数的值已经成功拼接了我们传入的../../../../../ public/index。跟踪调用栈来查看漏洞的触发过程,由于系统开启了多语言功能,发送的请求将会进入/src/think/middleware/LoadLangPack.php的handle方法。handle方法中调用detect方法,并将其返回的值赋值给$langset变量,然后判断langset是否为默认值,不是则带入到switchLangset方法。跟进detect方法,langSet初始为空,然后从get/header/cookie中判断是否存在对应的参数名,若有则赋值给langSet变量。get对应lang,header对应think-lang,cookie对应think_lang。此处的93行有一个allow_lang_list,看似有对langSet的判断逻辑,但搜索allow_lang_list发现其默认为空。这意味着此处其实没有任何过滤,直接将获得的langSet值传递给range变量并返回到上层函数。继续跟进switchlangset方法,其调用load。Load方法里判断$name是否为文件,若是则调用parse方法,parse方法中最终漏洞触发点include $file。显然,该漏洞只能实现php文件的包含。为了利用该漏洞,可以结合pearcmd的trick来实现RCE。pecl是PHP中用于管理扩展而使用的命令行工具,而pear是pecl依赖的类库。在7.3及以前,pecl/pear是默认安装的;在7.4及以后,需要我们在编译PHP的时候指定--with-pear才会安装。但是,在Docker任意版本镜像中,pcel/pear都会被默认安装,安装的路径在/usr/local/lib/php。Pear的pearcmd.php文件可以获取命令行参数并执行对应Commands,运行该文件可以看到它的功能。查看pearcmd.php,argv从$_SERVER['argv']中获得。PEAR_Command::setFrontendType('CLI');
$all_commands = PEAR_Command::getCommands();
// remove this next part when we stop supporting that crap-ass PHP 4.2
if (!isset($_SERVER['argv']) && !isset($argv) && !isset($HTTP_SERVER_VARS['argv'])) {
echo 'ERROR: either use the CLI php executable, ' .
'or set register_argc_argv=On in php.ini';
exit(1);
}
$argv = Console_Getopt::readPHPArgv();
// fix CGI sapi oddity - the -- in pear.bat/pear is not removed
if (php_sapi_name() != 'cli' && isset($argv[1]) && $argv[1] == '--') {
unset($argv[1]);
$argv = array_values($argv);
}
当php.ini开启register_argc_argv=On,用户输入可以赋值给$_SERVER['argv']:因此,攻击者可从web访问pearcmd的命令行功能,并传入命令行功能的参数。发送如下报文即在根目录创建test.php文件,内容含传入的<?=phpinfo(); ?>。访问test.php,可以看到已经成功执行phpinfo。发送如下报文即下载远端phpinfo.php到根目录,虽提示phpinfo.php不是tgz file,但仍可被成功下载。漏洞修复在官方的commit:https://github.com/top-think/framework/commit/c4acb8b4001b98a0078eda25840d33e295a7f099。核心是增加了校验,即如传入参数不符合正则表达式,最终被重置为默认的zh-cn。参考链接:
[1] https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp[2] https://y4tacker.github.io/2022/06/19/year/2022/6/%E5%85%B3%E4%BA%8Epearcmd%E5%88%A9%E7%94%A8%E6%80%BB%E7%BB%93/[3] https://tttang.com/archive/1865/#toc__6
文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2NDY1MDc2Mg==&mid=2247504223&idx=2&sn=50a3ac7e30a202c68b13ce384bbb2d48&chksm=cffa5fb689ded5459093bf18f55ba34fa6d38e512373144e95f2c06e0a93e49b1f33f77cc306&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh