这PPT值得好好理解,审计思路可拓展至任何语言的框架、前端、后端、数据库操作逻辑审计

如有翻译失误,参照原文混合阅读理解即可,pdf见附件

CVE-2018-12895: Authenticated File Deletion

我们在处理上传的媒体文件的WordPress组件中,发现了我们的第一个关键漏洞。与文件上传和文件管理有关的所有操作都容易受到这类漏洞的影响,如文件写入、文件删除和文件修改。同理我们就发现了这样一个“任意文件删除漏洞”。

该漏洞可通过有作者权限的已登录用户触发。原本这些用户只能编辑发布新博客文章,而不能使用高权限的管理功能,例如安装WordPress插件等。但通过使用此漏洞,作者可以获取管理员特权或在服务器上执行任意代码。

抽象划分媒体功能

当我们审计【媒体功能】操作文件的方式时,我们文章(一)中所述。将此功能分为一系列相关模块组件。

我们从文件的上传开始看。首先对上载的文件及其文件名进行:

  1. 由文件清理组件进行清理 (过滤组件)
  2. 通过文件管理组件移动到上传目录 (文件组件)
  3. 生成稿件Meta条目 (Meta组件)

这些Meta条目将有关上传文件的信息存储在数据库中,此信息包括例如文件名和上传时间等。稍后再次使用【Meta组件】来确定文件系统中的文件名,以便在【文件组件】中进行进一步的文件操作。我们先通过审计【Meta组件】来找到漏洞。由于文件上传的路径穿越漏洞和各种截断等技巧很早就已为人所知,并且在WordPress早就被过滤,因此我们认为【过滤组件】和【文件组件】基本上是安全的。而由于【Meta组件】是WordPress特有的,我们或许需要深入了解整个框架的体系结构知识才能利用这个点,因此审计此【Meta组件】我们或许、也许、可能、大概、至少能挖到些有限利用的漏洞或弱点,先挖挖看然后小本本记起,以便将其与另一个bug组合利用。

背景介绍:文件Meta条目

为了理解我们在WordPress【Meta组件】中发现的逻辑错误,我们首先需要对WordPress核心如何创建和使用Meta条目有一些基本了解。

当图像上传时,首先将其移动到上载目录wp-content/uploads,同时WordPress还将在数据库中为此图像创建内部索引,以跟踪Meta信息,例如图像的所有者或上载时间等。此Meta信息存储为数据库中的Meta条目,这些条目中的每一个都会分配特定的ID并保证key/value对应。

浏览WordPress数据库的wp_postmeta表,我们可以大致了解此处存储的数据。可见几个敏感的字符串:文件名和序列化数据。

下游组件未验证数据

在将【媒体功能】抽象为一系列组件之后,我们知道上传文件的文件名存储在数据库的一个库中。而WordPress4.9.9和5.0.1之前的Meta条目存在一个特性:“可修改任意条目为任意值”。 更新图片(例如更改图片注释)将调用edit_post()函数,而此函数直接通过继承$_POST数组带入内部变量。

从上面的代码看出,用户可以注入任意的Meta条目,由于未验证修改的条目,因此攻击者可以修改如_wp_attached_file等Meta条目为任何值。这样并不会重命名文件系统上的真实文件,而只是更改数据库中的这个文件名的值。

接下来,我们使用静态代码审计工具,自动化查找出引用了“可控为任意值Meta数据”这个弱点的几个功能。

最终,我们检测到删除文件时使用了Meta数据。 由于WordPress信任从上游【Meta组件】传入的值,因此它将直接删除所传入文件名的这个文件。这意味着攻击者可以通过任意设置_wp_attached_file的Meta数据为他想要删除的文件,以此来删除任何文件。然后,攻击者可以指示WordPress删除文件系统上的任何文件(相关RIPS漏洞报告)。

影响和局限性

攻击者可以使用此任意文件删除漏洞来删除WordPress的主要配置文件:wp-config.php。一旦此文件删除,WordPress就会识别为尚未安装状态。它将向网站用户显示WordPress安装步骤,攻击者可以重新安装WordPress,并可以控制数据库连接设置,他可以将其指向自己的远程数据库服务器。因此他可以加载新的管理员帐户并使用管理员功能。当此漏洞是由低权的作者账号权限完成提权的。此外,攻击者可以控制数据库中的关键WordPress设置,从而可以执行任意PHP代码。

此漏洞的局限性在于,尽管攻击者可以完全控制WordPress的安装,但通过删除包含数据库凭据的配置文件,他仍无法访问数据库中存储的数据。这样,用户帐户,博客文章,页面,文件和设计配置将丢失,真正的站点管理员将察觉到攻击存在。(草,鸡肋,忽略)

因此,我们决定根据【Meta组件】的问题挖掘一个更严重的漏洞,这将使攻击者不触发任何风控就能上传后门。

CVE-2019-8943:Authenticated Path Traversal and LFI

在确定了之前那个漏洞之后,我们根据Meta数据的使用情况,进一步跟进静态分析工具的报告并发现另一个漏洞。在WordPress的【图像编辑组件】中检测到路径遍历漏洞。更准确地说,它隐藏在裁剪功能中,一个可以由低权用户控制的图像操作功能。

为了利用此漏洞,我们必须将其与“本地文件包含”漏洞进行组合。接下来,我们将详细研究这两个漏洞。

分析图像裁剪功能

我们发现,低权用户可使用的【裁剪图像功能】也依赖于Meta条目将图像加载到裁剪窗口中(RIPS漏洞报告)。因此,我们对图像裁剪功能进行了分析,以了解利用Meta数据做为切入点需要满足的条件。

我们列举出以下图像上传到WordPress网站时的逻辑流程:

  1. 【文件管理组件】将图像移至上传目录wp-content/uploads
  2. 在数据库中创建对图像的内部索引以便跟踪元信息,例如图像的所有者或上载时间(Meta信息)低权用户想要裁剪图像时将获取要编辑的图像的ID
  3. 【Meta组件】从数据库中提取相应的_wp_attached_file中的Meta条目并传递下去
  4. 【图像编辑组件】收到Meta信息并将生成的图像传递下去
  5. 【文件管理组件】收到图像信息并将新图像保存回文件系统

我们可以控制传递给【图像编辑组件】的文件名,因此可以好好跟一下这个组件,研究是否可以以某种方式利用检测到的其他安全漏洞将任意图像传递过去。

图像编辑中的路径穿越

wp_crop_image()函数中存在“路径穿越”漏洞,当用户裁剪图像时,函数先获取要裁剪的图像ID($attachment_id),并从数据库中获取相应的_wp_attached_file的Meta条目。 这里注意,由于edit_post()的代码缺陷,导致攻击者可以控制get_post_meta()的返回值$src_file

下一步WordPress会确保图像真实存在并加载它,而WordPress有两种加载特定图像的方法:

  1. 第一种是简单地在wp-content/uploads目录(下一个代码片段的第2行)中查找_wp_attached_file的Meta条目作为的文件名。
  2. 如果方法1失败,则WordPress将尝试从其自己的服务器下载图像作为备份,它将生成一个下载URL,该URL包含wp-content/uploads目录的URL和_wp_attached_file中Meta条目存储的文件名(第6行)。

让我们举个例子:

如果_wp_attached_file的Meta条目中存储的值是evil.jpg,那么WordPress首先会尝试检查文件wp-content/uploads/evil.jpg是否存在,如果没有那它将尝试从类似如下URL下载文件:https://targetserver.com/wp-content/uploads/evil.jpg

WordPress尝试下载图像而不是在本地查找图像的原因是:当访问URL时插件可以即时生成图像。注意以下受影响的代码,构成图像URL时处理文件名会拼接/URL,而途中没有任何清理过滤。WordPress只是将上传目录和URL与$src_file拼接在一起,而$src_file可是我们可控的哦。(哟,有点意思了,真刺激)

WordPress通过wp_get_image_editor()成功加载了有效的文件后,将开始裁剪图像。然后将裁剪后的图像保存回文件系统(无论是否已下载)。最终的文件名将是get_post_meta()返回的$src_file值,再说一遍此处可控呵呵呵。而影响文件名字符串的唯一改动是:文件的基本名称前面加上字符串cropped-(下一个代码片段的第4行)。我们传入的evil.jpg示例文件名将变为cropped-evil.jpg

然后WordPress通过wp_mkdir_p()在最终路径中创建尚不存在的目录(第6行)。然后最终使用图像编辑器中的save()方法将图像写入文件系统,并且save()方法也不会对传入的文件名进行路径穿越过滤。

目前为止,我们已经确定可以控制哪个文件被加载到图像编辑器中,并且途中没有任何检查和过滤,知道了如果文件不是图像格式那编辑器将抛出异常。

所以第一个“猜想”:我们只能裁剪在上传目录之外的图像,但是如果WordPress进入下载图像的逻辑(本地找不到该图像),就能触发路径穿越漏洞。

这个猜想要实现,得将_wp_attached_file设置为evil.jpg?shell.php,这样框架就会对以下URL发出HTTP请求:https://targetserver.com/wp-content/uploads/evil.jpg?shell.php。该请求也将返回有效的图像文件,因为?之后的所有内容在HTTP上下文中将被忽略。生成的文件名就为evil.jpg?cropped-shell.php

可是虽然图像编辑器的save()方法不会检查“路径穿越”的payload,但它会把所加载图像的mime类型作为扩展名附加到生成的文件名后面,所以最终文件名将为evil.jpg?cropped-shell.php.jpg,那这还搞毛啊!别慌,如果我们加入路径穿越,就仍然有可能通过使用诸如evil.jpg?/../../evil.jpg之类的payload将结果图像上传任何目录中。

影响和局限性

本文讨论的第一个示例(上篇文章中)说到了WordPress的【主题组件】中有限LFI漏洞。因为只能包含来自某个目录的文件所以受限,并且不可能将文件写入当前可以执行包含的目录。

但现在我们可以将图像文件传入到任何目录中,这一事实低权攻击者可以利用原本有限的LFI那个洞。攻击者可以在图像的EXIF元数据部分注入PHP可执行代码,该代码将传入到他可以包括在其中的目录中。这样就能造成任意PHP代码执行。(此漏洞曾获 Pwnie Award 最佳服务器端bug奖)

与先前分析的任意文件删除漏洞相反,此漏洞的优点是更佳隐蔽,并且不会破坏站点上的任何数据。但是,它仍然需要与第一个漏洞相同的用户权限。所以我们的下一步是挖掘一个未验证的漏洞,或者使用历史遗留的未经身份验证的漏洞。总之将之前的努力全部串联起来,组成一个完整的exp-chain。

(未完待续...下篇见)

  • 翻译自《How we found 5 0days in WordPress》- RIPS Technologies

RIPSTECH-wordpress-security.pdf (1.702 MB) 下载附件
点击收藏 | 1 关注 | 2
  • 动动手指,沙发就是你的了!
登录 后跟帖