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

摘要


两周前,Drupal安全团队披露了一个非常严重的(21/25 NIST等级)漏洞,该漏洞又名为Drupalgeddon 2(SA-CORE-2018-002/CVE-2018-7600)。对于默认或常见的Drupal安装来说,该漏洞允许攻击者在未经身份验证的情况下远程执行代码。

Drupal是一款开源内容管理系统(CMS),用户多达100万以上(包括政府、电子零售、企业组织、金融机构等),除非已经安装了针对Drupalgeddon 2漏洞的安全补丁,否则,所有用户都会面临该漏洞的严重威胁。

到目前为止,该漏洞的详细信息尚未公开,但Check Point Research经过一番深入研究后,已经搞清了其背后的工作原理。

长话短说,引起该漏洞的根本原因,是由于Drupal对Form API(FAPI)的AJAX请求的输入没有进行严格过滤,使得攻击者有机会将恶意荷载注入内部表单结构,从而导致Drupal在没有进行用户认证的情况下执行恶意荷载。利用该漏洞,攻击者可以接管整个网站。

对于该漏洞来说,从Drupal 6到Drupal 8之间的所有版本都受其影响,即使手工安装更新的网站也不例外。在本文中,我们将以Drupal旗舰产品Drupal 8为例,为读者详细介绍开箱即用安装环境下的真实攻击情形。

技术细节


安全漏洞

Form API是在Drupal 6中引入的,它允许在表单渲染过程中修改表单数据——这彻底改变了标记的处理方式。

从Drupal 7开始,Form API被扩展至“渲染数组”。经过这次扩展之后,该API已经可以表示Drupal的大部分UI元素的结构了,例如页面、文本框、节点等。

渲染数组用于存放渲染过程中使用的元数据。这类数组采用键值结构,其中属性键以#开头,如:

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

Drupal提供的补丁


Drupal提供的补丁添加了一个名为RequestSanitizer的类,它带有一个stripDangerousValues方法,该方法的作用是将输入数组中的所有以井号开头的数据项全部“unset”(注:属性键以#开头)。同时,该方法会在Drupal启动初期(加载站点配置后立即)对$ _GET、$ _POST和$ _COOKIES中的输入数据进行相应的过滤处理。

这个补丁之所以这么做,据我们猜测,原因之一可能是为了提高该漏洞得发现和利用难度。

寻找攻击矢量


鉴于此,我们决定将精力全部集中到那些暴露给匿名用户的表单上面。

这些类型的表单有很多,其中之一是用户注册表单。该表单包含多个字段,具体如下所示。

图1:Drupal注册表单。

我们知道,要想利用该漏洞,就需要在表单结构中的某个地方注入渲染数组,所以,首先要找到注入位置。

碰巧的是,“Email address”字段没有对其收到的输入类型进行相应的过滤处理。这就意味着,我们能够向表单数组结构中注入一个数组(作为email字段的值)。

图2:将渲染数组注入到注册表单的mail输入中。

图3:注入渲染数组后的表单示例。

现在,我们只需要让Drupal渲染我们的注入数组就行了。不过,由于Drupal会将我们注入的数组视为值,而不是元素,因此,我们需要设法欺骗Drupal来渲染它。

这个Drupal渲染数组的功能:

  1. 页面加载
  2. Drupal AJAX API--即当用户填写AJAX表单时,向Drupal发出请求,以渲染HTML标记并更新表单。

在围绕上述功能考察了各种可能攻击途径之后,根据提交后的渲染过程以及Drupal的实现方式,我们得出结论:AJAX API调用是利用该漏洞的最佳选择。

"Picture"字段是用户注册表单的一部分,它可以使用Drupal的AJAX API将图像上传到服务器,并将其替换为上传图像的缩略图。

图4:通过AJAX API上传图像的表单。

我们仔细研究AJAX文件上传回调函数代码后发现,它使用GET参数来确定表单中哪些部分需要在客户端中进行更新操作。

图5:AJAX的“upload file”回调函数代码。

如果令element_parents指向存放我们注入的数组的表单部分的话,就能成功地让Drupal渲染它们。

利用Drupalgeddon 2漏洞


为了利用这个安全漏洞,只需注入一个恶意渲染数组,然后让该数组利用Drupal的渲染回调函数在系统上执行代码就行了。

实际上,我们可以注入 下列属性:

  • #access_callback
    该元素供Drupal用来确定当前用户是否有权访问某元素。
  • #pre_render
    在渲染之前操作渲染数组。
  • #lazy_builder
    用于在渲染过程结束时添加元素。
  • #post_render
    接收渲染过程的结果,并对其进行封装。

在本POC中,我们选择将#lazy_builder元素注入到了邮件数组中。借助于AJAX API回调函数,我们就可以让Drupal来渲染我们的恶意数组了。

如此一来,我们就能够控制管理员的帐户,安装恶意的后门模块,并最终在服务器上执行任意命令了。

图6:将恶意命令注入到Drupal的渲染回调函数中。

图7:使用恶意模块成功执行shell命令。

小结


在阅读Twitter和几个安全博客上关于该漏洞的介绍后,我们发现安全社区对于这个漏洞公告感到非常困惑,有些人甚至怀疑它的严重性。因此,我们认为值得深入研究。然而,这项研究的挑战性在于,由于安全补丁故意掩盖了真正的攻击向量,所以我们不得不面对大量可能的攻击向量。为了加快我们的研究,我们有幸邀请到了Drupal平台的相关专家,在此致以衷心的感谢。

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖