ThinkPHP5长途代码执行缝隙 8090安适门户
ThinkPHP是一个免费开源的快速、简单、面向东西的轻量级PHP开发框架,是为了敏捷Web应用开发和简化企业应用开发而诞生。
ThinkPHP 5.0版本是一个颠覆和重构版本,给与全新的架构思想,引入了更多的PHP新特性,优化了核心,减少了依赖,实现了真正的惰性加载,撑持composer,并针对API开发做了大量的优化。
ThinkPHP官方2018年12月9日颁布修复了一个严重的长途代码执行缝隙。该更新主要涉及一个安适更新,由于框架对控制器名没有进行足够的检测会导致在没有开启强制路由的情况下可能的getshell缝隙。
受影响的版本包孕5.0和5.1版本,保举尽快更新到最新版本。
道理这个缝隙是由于框架对控制器名没有进行足够的检测而导致在没有开启强制路由的情况下可能的getshell。
因此缝隙的触发在路由调理时。
Thinkphp中是由函数pathinfo()来获取路由的,因此我们可以搜索关键词pathinfo,来定位函数。
该路由函数中$this->config['var_pathinfo']是配置文件的默认值,其初始化代码如下,值为‘s’:
当请求报文包罗$_GET['s'],就取其值作为pathinfo,并返回pathinfo给挪用函数。
分析发明pathinfo函数被library/think/Request.php中的path函数挪用:
显然,这里$this->path源自pathinfo,因此可以被恶意访谒者控制。继续分析该变量的通报,在library/think/App.php中被引用:
这里是进行路由检测,恶意访谒者可控的$path被通报给了如下的check函数:
thinkphp/library/think/Route.php分析代码可知,如果开启了强制路由则会抛出异常
Check函数最后实例化一个UrlDispatch东西,将$url通报给了结构函数。继续分析UrlDispatch的父类也就是Dispatch类的结构函数:
/thinkphp/library/think/routeDispatch.php$dispatch变量可控并赋值给了$this->dispatch,颠末多次函数挪用返回,最后如下的Url类的init 函数将会被挪用来措置惩罚惩罚$this->dispatch。
/thinkphp/library/think/route/dispatch/Url.php这里挪用parseUrl对$this->dispatch进行解析,这是该缝隙的核心点之一:
这里挪用parseUrlPath函数对$url进行解析,继续分析该函数:
/thinkphp/library/think/route/Rule.php显然,url的格局为“模块/控制器/操纵”,url的格局为“模块/控制器/操纵”,url支解形成一个数组存到$path变量中并返回到挪用者。
继续分析封装路由的代码:
library/think/route/dispatch/Url.php路由封装返回到library/think/route/dispatch/Url.php
$result就是封装好的路由数组,通报给了Module的结构函数。
由于Module也是担任自Dispatch类,直接看Dispatch的结构函数:
$result赋值给了$this->dispatch。然后挪用Module类的init函数:
\thinkphp\library\think\route\dispatch\Module.php public function init() { parent::init(); $result = $this->dispatch; if (is_string($result)) { $result = explode('/', $result); } if ($this->rule->getConfig('app_multi_module')) { // 多模块部署 $module = strip_tags(strtolower($result[0] ?: $this->rule->getConfig('default_module'))); $bind = $this->rule->getRouter()->getBind(); $available = false; if ($bind && preg_match('/^[a-z]/is', $bind)) { // 绑定模块 list($bindModule) = explode('/', $bind); if (empty($result[0])) { $module = $bindModule; } $available = true; } elseif (!in_array($module, $this->rule->getConfig('deny_module_list')) && is_dir($this->app->getAppPath() . $module)) { $available = true; } elseif ($this->rule->getConfig('empty_module')) { $module = $this->rule->getConfig('empty_module'); $available = true; } // 模块初始化 if ($module && $available) { // 初始化模块 $this->request->setModule($module); $this->app->init($module); } else { throw new HttpException(404, 'module not exists:' . $module); } } // 是否自动转换控制器和操纵名 $convert = is_bool($this->convert) ? $this->convert : $this->rule->getConfig('url_convert'); // 获取控制器名 $controller = strip_tags($result[1] ?: $this->rule->getConfig('default_controller')); $this->controller = $convert ? strtolower($controller) : $controller; // 获取操纵名 $this->actionName = strip_tags($result[2] ?: $this->rule->getConfig('default_action')); // 设置当前请求的控制器、操纵 $this->request ->setController(Loader::parseName($this->controller, 1)) ->setAction($this->actionName); return $this;这里存在第一个对$module的判断,需要让$available即是true,这就需要iis_dir(this->app->getAppPath() . module)创立。
官方demo给出的模块是index,而实际开发措施不必然存在该模块名,所以结构payload时这里是一个注意点。
满足这个判断条件后,继续分析后续的控制流会进入如下module的exec函数:
分析发明,$this->controller是恶意访谒者可控的,并通报给了如下的controller函数,继续分析该函数:
\thinkphp\library\think\App.php
在这里,name是恶意访谒者可控的,并通报给了如下的parseModuleAndClass函数:
温馨提示: 本文由杰米博客推荐,转载请保留链接: https://www.jmwww.net/file/pc/12450.html