首页
社区
课程
招聘
[翻译]Adobe Flash漏洞利用:从CVE-2015-5119到CVE-2018-4878
发表于: 2018-3-4 00:26 5510

[翻译]Adobe Flash漏洞利用:从CVE-2015-5119到CVE-2018-4878

2018-3-4 00:26
5510



上周,据报道,一个exp(漏洞利用)被用来传播ROKRAT恶意软件。有趣的是,Flash exp“销声匿迹”了一段时间,现在又出现,在被一个APT组织利用。我们不禁想知道发生了什么变化,以及这个最新exp的原理。


在这篇文章中,我们将先介绍一个旧的Flash exp,然后了解这个最新的样本如何绕过Flash环境中的一些防御措施。


先来看看之前一个影响Flash防御措施的漏洞,CVE-2015-5119,通常被称为Hacking Team Flash 0day。


早在2015年7月,Hacking Team遭遇了一次数据泄露,一些内部电子邮件、应用程序源码和exp被公开,其中包含针对一个Flash 16的远程代码执行漏洞(即CVE-2015-5119)的exp。


该漏洞类型为“Use-After-Free”,意味着在没有更新对象引用的情况下内存被释放给Flash使用。来看一个可以触发漏洞的示例:


查看Flash的源码,我们可以了解产生这个漏洞的原因。首先,有一个长度为0xfa0的ByteArray,我们给它分配一个对象。查看相应的源码,会看到“ByteArrayObject :: setUintProperty”负责处理这个任务:

例子中“value”参数是一个对象引用,被传递给检查类型的“AvmCore :: integer”函数:

然后参数被传递给“number”方法:

我们的对象被传递给“AvmCore :: atomToScriptObject”,它将该值转换回“ScriptObject”:

最后,调用“valueOf”属性:

现在我们理解了这个漏洞,下面来看看它是如何被利用的。


在利用这种Flash漏洞时,我们想用一个对象来填充释放的内存,并且允许我们控制执行或修改内存…输入Vector.<uint>。Vector对象非常简单,初始化方法如下:

初始化后,对象将包含以下内存布局:

可以在ActionScript中使用以下代码检索Vector.<uint>的长度:

该矢量的内容通过以下方式检索:

现在要修改“Length”属性,我们发现有一个相当强大的R/W(读/写)原语。例如,如果能用0xFFFFFFFF填充“Length”属性的内存,我们就可以操控任意内存。


更新exp来展示这一点:

我们采取了以下步骤:


这导致了内存的任意读/写,使用户能够编写shellcode并强制执行。


在2015年7月16日发布的一篇帖子中,Google Project Zero参考了Hacking Team的exp,并宣布他们已经与Adobe合作推出了一些强化Flash的方法。完整的帖子可在这里找到,其中介绍了3种强化方法:


在这三种对抗方法中,上述的修改Vector.<uint>的length属性的技术,有两种方法可以对抗。首先,Vectors被移动到一个单独的内存区域,与任何可能允许篡改“length”属性的潜在溢出隔离。其次,在Vector对象中引入了一些检查,以确保如果“length”属性被修改,运行时将检测到这种修改并暂停执行。


这种长度验证方法是以XOR key实现的。与stack-canaries类似,Vector对象中的一些属性与一个key异或,并存储结果值,这是一个检测损坏数据的简单方法。


对抗措施发布后,事情似乎平静下来。然而,一个新的漏洞出现了,CVE-2018-4878


该漏洞的细节未公开,与许多安全研究人员一样,我们抓取了一个恶意软件的样本,并开始对样本进行逆向分析。


获取SWF文件并反汇编,我们发现在加载SWF时,会向C2服务器发出请求:



响应中包含一个key,该key可解密嵌入的SWF exp:



不幸的是,过程到此搁置。我们分析的所有样本中看到C2服务器都无法访问,意味着我们无法恢复100字节的XOR解密key来分析该exp。此外,那些幸运地拥有解密key的人不太愿意与他人分享,也就是说我们能做的只有等待细节被披露。


慢慢地细节开始被公开,以编辑过的部分截图和与该漏洞相关的帖子的形式出现,但没有显示获得R/W原语的路径。经过几个熬夜工作之后,我们能够重建漏洞并了解绕过对抗措施的一些情况。


首先,我们看看如何用一个简单的实例触发漏洞:

漏洞存在于DRMManager的“initialize”调用中,需要一个继承DRMOperationCompleteListener接口的对象。 在可以使用之前,通过将“this.listener”设置为NULL来释放对象,强制分配的内存由garbage collector(垃圾收集器)释放。


接下来,我们分配一个DRMOperationCompleteListener对象,并在“danglingpointer”变量中保存对其的引用。 这个对象被释放,但是“danglingpointer”变量仍然引用其内存,这意味着形成了一个use-after-free条件。


继续查看所披露的exp,我们看到加了一个计时器:

该计时器调用一个新的函数检查UAF条件:

这个定时器用于定期检查我们的“danglingpointer”对象是否已释放,并且现在指向已释放的内存。最终情况就是,允许我们用另一个对象填充这个空闲空间。


在这一点上,情况变得有点朦胧。在我们发现的截图和示例中,似乎都没有分享生成填充此内存的对象的类(“Mem_Arr” 类)的细节。但是,我们确实找到了利用此漏洞的方法,重新让我们理解了该类的行为,但是如果你有该恶意软件的样本,我们有兴趣知道你和我们对该恶意软件漏洞利用分析的匹配度。


从网上的讨论中知道,用于控制Flash的原语是一个ByteArray,意味着我们要用一个ByteArray对象填充释放的内存:



但问题是我们知道由于大小的差异,ByteArray可能不会被分配到释放的DRMOperationCompleteListener对象的内存位置。然而,我们可以创建一个新的继承ByteArray类的类并添加其他属性来扩展对象的大小。为此,我们创建一个新的类“Mem_Arr”:

此外,修改“MyListener”对象以包含更多属性:

原因是为了确保“MyListener”和“Mem_Arr”对象的大小相似,从而允许我们用“Mem_Arr”替换释放的“MyListener”对象内存。


我们还将更新“uafcheck”函数,从“Mem_Arr”对象中转储内存,以确保我们处于正确的方向上:

现在,执行此SWF,会发现我们的跟踪日志包含以下内容:

第一眼看起来像DWORD的随机序列,我们看看具体是什么。首先,我们看到“0x31”的值,实际上这是更新的ByteArray/Mem_Arr对象的“position”属性值。


查看ByteArray类的源码,我们知道ByteArray由以下属性组成:

其中一个属性是“m_position”,它包含“position”属性,这意味着我们处于正确的方向上,现在有能力操纵ByteArray的底层内存。


实际上使我们感兴趣的是在“m_buffer”属性中发现的一个指向包含以下内容的Buffer对象的指针:

这里我们看到Google Project Zero引入的对抗措施之一,一些用作XOR检查值的属性。 我们需要通过解引用(dereference)m_buffer的地址来访问此结构。


为此,我们添加了一个新的类:

并从我们的Mem_Arr类添加了对这个类的引用:

这里的想法是通过悬挂指针指向“m_buffer”地址来设置“Mem_Arr”对象的“o1”属性,然后通过“Modify”类来解引用对象。更新“o1”属性如下:

执行时,看见返回如下的记录:

这里可以清楚地看到ByteArray的长度为0x512,再次表明我们处于正确的方向。用这些值覆盖ByteArray对象:


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2018-3-4 00:49 被SpearMint编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 65
活跃值: (27)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2

接下来,我们分配一个DRMOperationCompleteListener对象,并在“danglingpointer”变量中保存对其的引用。 这个对象被释放,但是“danglingpointer”变量仍然引用其内存,这意味着形成了一个use-after-free条件。


跟着exp的漏洞行为也能理解,但没搞清danglingpointer指向的对象是谁释放的?还是这个对象new了之后一段时间没用自己释放了?
2018-3-8 10:37
0
游客
登录 | 注册 方可回帖
返回
//