Yii2框架Gii模块 RCE 分析

 

利用周末时间分析了Yii2框架的一个RCE漏洞,利用了框架可以写PHP模板的功能,控制写入的内容为恶意代码,实现对指定的文件写入php 命令执行语句,调用PHP从而获取系统权限。

 

0x01 Yii 介绍

Yii 是一个高性能,基于组件的 PHP 框架,用于快速开发现代 Web 应用程序。一个通用的 Web 编程框架,即可以用于开发各种用 PHP 构建的 Web 应用。 因为基于组件的框架结构和设计精巧的缓存支持,它特别适合开发大型应用, 如门户网站、社区、内容管理系统(CMS)、 电子商务项目和 RESTful Web 服务等。

  • 和其他 PHP 框架类似,Yii 实现了 MVC(Model-View-Controller) 设计模式并基于该模式组织代码。
  • Yii 非常易于扩展。
  • Yii 的代码简洁优雅。

 

0x02 环境搭建

利用docker 原生ubuntu镜像搭建漏洞调试环境

0x01 composer 安装

Composer 是 PHP 的一个依赖管理工具。它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们。

你可以将此文件放在任何地方。如果你把它放在系统的 PATH 目录中,你就能在全局访问它。 在类Unix系统中,你甚至可以在使用时不加 php 前缀。
你可以执行这些命令让 composer 在你的系统中进行全局调用:

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

0x02 yii2 安装

安装composer过后,需要安装git 以及php插件,composer在安装yii2框架时会从git上clone项目,只不过不保留.git文件夹。

apt install apache2 php 
apt install zip unzip git php-mbstring php-curl php-dom -y
composer create-project --prefer-dist yiisoft/yii2-app-basic basic

至此yii2框架就基本搭建完成了,有了composer 之后确实方便了很多。

0x03 数据库搭建及连接

利用docker搭建数据库,注意在数据库中创建新库和数据表

docker run  --name mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
vim /var/www/html/basic/config/db.php

0x04 Xdebug 安装

pecl PHP Extension Community Library的缩写,即PHP 扩展库。https://pecl.php.net/
PECL是使用C语言开发的,通常用于补充一些用PHP难以完成的底层功能,往往需要重新编译或者在配置文件中设置后才能在用户自己的代码中使用。

利用pecl 安装xdebug 并进行配置

apt-get install php-pear 
apt-get install php-phpize
pecl install xdebug

将xdebug.so与php相关联,xdebug.ini 配置如下

zend_extension=/usr/lib/php/20190902/xdebug.so
xdebug.remote_enable=1
xdebug.remote_connect_back=0
xdebug.remote_host=172.19.0.12
xdebug.remote_port=9000

向apache的php配置添加xdebug.ini配置文件,并重启服务

cp  /usr/share/php/docs/xdebug/xdebug.ini /etc/php/7.4/apache2/conf.d/


service apache2 restart

0x05 远程调试配置

因为服务在服务器端,本地需要phpstorm调试需要配置端口转发,将本地端口转到服务器上去。又因为服务在服务器docker内部因此也需要把ssh端口转发出来。操作如下

在服务器执行

在docker内执行

在本地执行

配置phpstorm,进行远程文件关联

配置sftp

0x06 添加白名单

gii 默认添加了白名单访问,这里只需加个*就可以了

 

0x04 漏洞利用

0x1 生成恶意代码文件

所有环境都配置好后,选择创建的数据表并制定类名

在Message Category字段处填写恶意代码,如下图所示

0x2 触发恶意文件

 

0x03 漏洞原理及调试

0x0 漏洞原理

yiisoft/yii2-gii/src/Generator.php#L505 存在参数拼接,而且没有检查用户传递的参数。

0x1 路由介绍

yii用了统一的路由分发,路由的工作可以分为两步:

  1. 从请求中解析出一个路由和相关参数;
  2. 根据路由生成响应的控制器操作,来处理该请求。

1. 解析参数

Application.php:103, yii\web\Application->handleRequest()

从url中获取route 和 参数

调用栈关系

Request.php:699, yii\web\Request->getQueryParam()
UrlManager.php:365, yii\web\UrlManager->parseRequest()
Request.php:275, yii\web\Request->resolve()
Application.php:82, yii\web\Application->handleRequest()
Application.php:386, yii\web\Application->run()
index.php:12, {main}()

0x2 生成控制器

Module.php:522, yii\web\Application->runAction()

具体实现将url get参数分割成id和route,匹配是不是已配置 module

如果不是已有module那么将会根据id生成controller

完整调用栈如下

Module.php:643, yii\web\Application->createControllerByID()
Module.php:596, yii\web\Application->createController()
Module.php:522, yii\web\Application->runAction()
Application.php:103, yii\web\Application->handleRequest()
Application.php:386, yii\web\Application->run()
index.php:12, {main}()

最后在runwithParams函数中完成类函数调用

0x2 可控参数传递链

在生成恶意代码的时候,是将我们传入的post参数写了进去。这个过程还是比较复杂的,调试跟了下归结为几个步骤。

  1. actionPreview功能将收到的post参数解析带入到$generator对象中
  2. actionPreview将解析好的对象成员保存为json格式在runtime目录下
  3. actionView读取json格式数据并解析成对象成员变量
  4. 调用到renderFile生成php code并将其写入文件中

1. actionPreview post参数解析

在DefaultController类中

2. actionPreview 保存为json

该操作将post包中的参数保存为json格式,并存储到文件中

3. actionView 读取json文件

从json文件中解析类成员变量

4. 文件生成

漏洞生成的文件如下

 

0x04 补丁分析

简单的加了个过滤

 

0x05 参考链接

https://github.com/yiisoft/yii2-gii/issues/433

https://lab.wallarm.com/yii2-gii-remote-code-execution/

(完)