2020-11-13 11:18:119965人阅读
1、前言
Nette Framework 是个强大,基于组件的事件驱动 PHP 框架,用来创建 web 应用。Nette Framework 是个现代化风格的 PHP 框架,主要用于国外网站开发,因此国内对该框架的研究比较少。2020年10月,Nette框架被爆出存在未授权任意代码执行漏洞,可通过自有框架控制器MicroPresenter执行任意PHP方法,我们对漏洞进行了复现和分析,发现该漏洞危害严重,请广大用户及时进行升级修复。
2、环境准备
通过查询发现该漏洞影响自2.0以来的几乎所有大版本,详细的范围如下
nette/application 3.0.6 (or 3.0.2.1, 3.1.0-RC2 or dev)
nette/application 2.4.16
nette/application 2.3.14
nette/application 2.2.10
nette/nette 2.1.13
nette/nette 2.0.19
我们通过composer安装受影响的3.0.0版本,执行composer create-project nette/web-project nette-blog 3.0.0@dev,安装完成后整体的目录结构如下:
其中app为应用程序的主目录,包含presenters控制类目录、config配置文件、router路由器类目录以及Booting.php应用启动文件。而vendor/nette目录下包含Nette的所有框架文件,www目录包含整个Web程序能够直接访问的文件,如静态资源、入口文件index.php等,同时在index.php中调用Booting中的boot方法引导启动。
Nette会创建Configurator类对象来对启动环境进行配置,如设置日志文件目录、临时文件目录、加载配置文件等。
后续会根据配置调用createContainer创建一个DI容器,并通过getByType方法实例化Nette框架主程序Nette\Application\Application对象,最后调用了Application对象的run方法。
3、漏洞分析
我们还是根据网上披露的POC来进一步分析代码,从Application:run函数处打下断点,函数会调用createInitialRequest方法来初始化Request对象。
跟进到createInitialRequest方法,108行通过调用路由类的match方法来处理http请求,109行则是获取需要调用的控制器类,119行则是返回处理好的Request对象。
我们跟进match方法,发现路由器类的调用路径如下:
Nette\Application\Routers\RouteList->Nette\Routing\RouteList->Nette\Application\Routers\Route->Nette\Routing\Route::match(),该方法主要将http请求处理后转换成数组。121行将网站请求路径中的基础路径删除赋值给$path,131行将$path按照presenter/action/id形式的正则进行匹配,并将匹配的部分分别标记为p0、p4、p13,148行则将匹配出的字符型key从$this->aliases数组中取出对应的描述字段,其中p0对应为presenter,因此取出的控制器为$params[‘presenter’]= nette.micro。
继续跟进到173行,调用了$params[$name] = $meta[self::FILTER_IN]((string) $params[$name])处理$params,其中$meta[self::FILTER_IN]对应了path2presenter处理控制器部分,将nette.micro转成Nette:Micro。
随后我们返回Application.php中的processRequest方法,这里我们主要关注控制器部分Nette:Micro如何被调用的,跟进114行到presenterFactory类的formatPresenterClass方法,调用路径为createPresenter->getPresenterClass->formatPresenterClass。
在该方法中,120行将$presenter用冒号分割,并对$mapping赋值为$this->mapping[‘Nette’]。
126行则将$mapping的第三个元素*Presenter中的*替换为Micro,并将$mapping的第一个元素和替换后的字符串相连,最终得到控制器为NetteModule\MicroPresenter。在Application.php的144-149行,程序调用了控制器NetteModule\MicroPresenter中的run函数,对应为nette/application/src/Application/MicroPresenter.php,69行获取传递进来的GET参数。
其中74行会检查callback参数传递进来的变量可否被当做函数调用,85行调用combineArgs方法获取回调函数中的默认参数名,并于GET请求传递过来的参数名比对,如果相同则保存在$res数组并返回到$params中。
返回到MicroPresenter.php的90行,这是一个典型的可变函数调用,在诸多PHP后门中比较常见,这里函数名$callback和参数$params都可控,可导致任意代码执行。我们以shell_exec方法为例,默认参数为cmd,我们构造对应的POC请求:
4、安全产品解决方案
百度度御关WAF、高级威胁感知系统,以及智能安全一体化产品已支持该漏洞的检测和拦截,有需要的用户可以访问anquan.baidu.com联系我们。
参考链接:
https://blog.nette.org/en/cve-2020-15227-potential-remote-code-execution-vulnerability
https://www.kancloud.cn/aspvb/nette/271800