漏洞分析

Drupal 在 3 月 28 日爆出一个远程代码执行漏洞,CVE 编号 CVE-2018-7600,通过对比官方的补丁,可以得知是请求中存在 # 开头的参数。Drupal Render API 对于 # 有特殊处理,比如如下的数组:

$form['choice_wrapper'] = array('#tree' => FALSE, '#weight' => -4, '#prefix' => '<div class="clearfix" id="poll-choice-wrapper">', '#suffix' => '</div>',
);

比如 #prefix 代表了在 Render 时元素的前缀,#suffix 代表了后缀。

通过查阅 Drupal 的代码和文档,可以知道,对于 #pre_render#post_render#submit#validate 等变量,Drupal 通过 call_user_func 的方式进行调用。

在 Drupal 中,对于 #pre_render 的处理如下:

// file: \core\lib\Drupal\Core\Render\Renderer.php
if (isset($elements['#pre_render'])) {foreach ($elements['#pre_render'] as $callable) {if (is_string($callable) && strpos($callable, '::') === FALSE) {$callable = $this->controllerResolver->getControllerFromDefinition($callable);}$elements = call_user_func($callable, $elements);}}

所以如果我们能将这些变量注入到 $form 数组中,即可造成代码执行的问题。

但是由于 Drupal 代码复杂,调用链很长,所以导致了所谓“开局一个 #,剩下全靠猜”的尴尬局面,即使知道了漏洞触发点,但是找不到入口点一样尴尬。直到昨日,CheckPoint 发布了一篇分析博客,我才注意到原来 Drupal 8.5 提供了 Ajax 上传头像的点,并且明显存在一个 $form 数组的操纵。在已经知道触发点的情况下,构造剩下的 PoC 就非常容易了。

PoC 构造

CheckPoint 提供的截图显示,是在 Drupal 8.5.0 注册处,漏洞文件为:\core\modules\file\src\Element\ManagedFile.php,代码如下:

public static function uploadAjaxCallback(&$form, FormStateInterface &$form_state, Request $request) {/** @var \Drupal\Core\Render\RendererInterface $renderer */$renderer = \Drupal::service('renderer');$form_parents = explode('/', $request->query->get('element_parents'));// Retrieve the element to be rendered.$form = NestedArray::getValue($form, $form_parents);// Add the special AJAX class if a new file was added.$current_file_count = $form_state->get('file_upload_delta_initial');if (isset($form['#file_upload_delta']) && $current_file_count < $form['#file_upload_delta']) {$form[$current_file_count]['#attributes']['class'][] = 'ajax-new-content';}// Otherwise just add the new content class on a placeholder.else {$form['#suffix'] .= '<span class="ajax-new-content"></span>';}$status_messages = ['#type' => 'status_messages'];$form['#prefix'] .= $renderer->renderRoot($status_messages);$output = $renderer->renderRoot($form);

代码第五行,取出 $_GET["element_parents"] 赋值给 $form_parents,然后进入 NestedArray::getValue 进行处理:

public static function &getValue(array &$array, array $parents, &$key_exists = NULL) {$ref = &$array;foreach ($parents as $parent) {if (is_array($ref) && (isset($ref[$parent]) || array_key_exists($parent, $ref))) {$ref = &$ref[$parent];}else {$key_exists = FALSE;$null = NULL;return $null;}}$key_exists = TRUE;return $ref;
}

NestedArray::getValue 函数的主要功能就是将 $parents 作为 key path,然后逐层取出后返回。举个例子,对于数组:

array("a" => array("b" => array("c" => "123","d" => "456"))
)

及 $parentsa/b/c,最后得到的结果为 456

查看一下在正常上传中,传入的 $form

似乎 #value 是我们传入的变量,尝试注入数组:

发现成功注入:

那么通过 NestedArray::getValue 函数,可以传入 element_parents 为 account/mail/#value,最后可以令 $form 为我们注入的数组:

在 Render API 处理 #pre_render 时候造成代码执行:

Exploit 构造

虽然实现了代码执行,但是 #pre_render 调用的参数是一个数组,所以导致我们不能任意的执行代码。不过 Render API 存在很多可以查看的地方,通过翻阅 Renderer::doRender 函数,注意到 #lazy_builder

  $supported_keys = ['#lazy_builder','#cache','#create_placeholder','#weight','#printed'];$unsupported_keys = array_diff(array_keys($elements), $supported_keys);if (count($unsupported_keys)) {throw new \DomainException(sprintf('When a #lazy_builder callback is specified, no properties can exist; all properties must be generated by the #lazy_builder callback. You specified the following properties: %s.', implode(', ', $unsupported_keys)));}
}
...
// Build the element if it is still empty.
if (isset($elements['#lazy_builder'])) {$callable = $elements['#lazy_builder'][0];$args = $elements['#lazy_builder'][1];if (is_string($callable) && strpos($callable, '::') === FALSE) {$callable = $this->controllerResolver->getControllerFromDefinition($callable);}$new_elements = call_user_func_array($callable, $args);...
}

#lazy_builder 是一个 array,其中元素 0 为函数名,元素 1 是一个数组,是参数列表。接着利用 call_user_func_array 进行调用。不过注意到上方这段代码:

$unsupported_keys = array_diff(array_keys($elements), $supported_keys);

意思为传入的 $elements 数组中不能存在除了 $supported_keys 之外的 key,常规传入的数组为:

比要求的数组多了 #suffix 和 #prefix。不过 Render API 有 children element 的说法:

// file: \core\lib\Drupal\Core\Render\Element.php
public static function children(array &$elements, $sort = FALSE) {...  foreach ($elements as $key => $value) {if ($key === '' || $key[0] !== '#') {if (is_array($value)) {if (isset($value['#weight'])) {$weight = $value['#weight'];$sortable = TRUE;}else {$weight = 0;

当数组中的参数不以 # 开头时,会当作 children element 进行子渲染,所以我们传入 mail[a][#lazy_builder] ,在进行子渲染的过程中,就会得到一个干净的数组,最终导致命令执行。

其他版本

本文分析的是 Drupal 8.5.0,对于 8.4.x,在注册时默认没有上传头像处,但是也可以直接进行攻击,对于 Drupal 7,暂时未找到可控点。

Reference

https://research.checkpoint.com/uncovering-drupalgeddon-2/

靶机环境:

https://github.com/vulhub/vulhub/blob/master/drupal/CVE-2018-7600/README.zh-cn.md

poc:

https://github.com/a2u/CVE-2018-7600/blob/master/exploit.py

drupal cve-2018-7600 远程代码执行漏洞 简介相关推荐

  1. 代码审计之CVE-2017-6920 Drupal远程代码执行漏洞学习

     1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...

  2. Drupal 修复远程代码执行漏洞

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 周三,Drupal 内容管理系统 (CMS) 发布更新,修复了和不正确清理所上传文件名称有关的一个远程代码执行漏洞 (CVE-2020 ...

  3. php x24 x65 x6d x61,Jboss远程代码执行漏洞CVE:2013-4810获得system权限

    此方法成功的渗透至Windows系统并获得最高权限exp 此方法成功的渗透至Windows系统并获得最高权限 exp ?php/*Apache Tomcat/JBoss EJBInvokerServl ...

  4. 绿盟安全事件响应观察及远程代码执行漏洞

    人和管理成为主要入侵突破口 安全需要人.技术.管理的全方位保障,然而人与管理由于其复杂性,常常成为入侵突破口.在 19 年处理的安全事件 中,弱口令事件占比 22%,钓鱼邮件相关事件占比 7%,配置不 ...

  5. CVE-2018-8174 IE浏览器远程代码执行漏洞

    0x00漏洞简介 在2018年5月9日的时候360发表了一份apt攻击分析及溯源报告 文中提到了cve-2018-8174这个漏洞的首次在apt方面的应用 原文地址:http://www.4hou.c ...

  6. 微软远程桌面服务远程代码执行漏洞

    人和管理成为主要入侵突破口 安全需要人.技术.管理的全方位保障,然而人与管理由于其复杂性,常常成为入侵突破口.在 19 年处理的安全事件中,弱口令事件占比 22%,钓鱼邮件相关事件占比 7%,配置不当 ...

  7. 绿盟科技网络安全威胁周报2017.17 请关注Squirrelmail 远程代码执行漏洞CVE-2017-7692...

    绿盟科技发布了本周安全通告,周报编号NSFOCUS-17-17,绿盟科技漏洞库本周新增84条,其中高危40条.本次周报建议大家关注 Squirrelmail 远程代码执行漏洞 .SquirrelMai ...

  8. cve-2017-12617 tomcat远程代码执行漏洞复现测试

    0x00前情提要 Apache Tomcat团队10月3日宣布,如果配置了默认servlet,则在9.0.1(Beta),8.5.23,8.0.47和7.0.82之前的所有Tomcat版本都包含所有操 ...

  9. wordpress 5.0.0 远程代码执行漏洞分析cve-2019-8943

    近日,wordpress发布一个安全升级补丁,修复了一个WordPress核心中的远程代码执行漏洞.代码修改细节可以参考wordpress团队于Dec 13, 2018提交的代码.据漏洞披露者文中所介 ...

最新文章

  1. 敏捷个人架构图 V1.3
  2. linux 删除o开头的文件,linux实现除了某个文件或某个文件夹以外的全部删除
  3. 试用Mono Beta 1.0
  4. android fragment framelayout,framelayout中fragment的切换
  5. php字节怎么转化成字符串,php将utf-8(3字节)字符串转换成字节
  6. 关闭和启动Oracle的几种方法总结
  7. 去哪儿:腊月二十九的火车线路有余票 机票价格低于往年
  8. 分享一些Java常见的面试题,大厂都爱用
  9. 经典排序算法(十一)--堆排序Heap Sort
  10. pycharm快捷键大全
  11. IOS 模拟器清除缓存
  12. 计算机在通风网络中的应用,普适计算在煤矿通风网络解算中的应用研究
  13. 10+ 张图来探究 Linux 内核,以及如何高效学习
  14. 电脑维护入门 GHOST 使用方法 图解说明
  15. 如何查询主机IP地址
  16. colab 跑 deformable-detr 记录:
  17. 2021-2022学年广州市育才实验学校九年级第一学期期中考试英语试题
  18. python的StringIO
  19. picturebox绑定datagridview
  20. 2016{太原UI设计师}郭文军讲解UI设计版式

热门文章

  1. 云网融合 — 云网之争
  2. 自动化生成 Openstack 新项目开发框架
  3. 电动滑板改装 特斯拉电机 120A FVT电调的使用
  4. 中消协上午发布报告 跨境电商假货等仍旧是毛病
  5. shape(15,)与(15,1)的区别
  6. C++之编码问题(Unicode,ASCII,本地默认)
  7. Spring Boot配置视图解析器
  8. storm集群和单点安装
  9. slc、mlc、tlc闪存芯片颗粒区别介绍
  10. ha-2:read-project-properties (default) on project