我个人对内存漏洞攻防战的一些见解

2022-12-22 14:39:39 浏览数 (1)

今天看到了铁磊师兄和张超老师以及yuange等大牛朋友圈发的关于内存漏洞攻防方面的讨论和真知灼见,受益匪浅。内存破坏漏洞的攻防战已经持续20多年,我虽然在2016年才开始近距离围观这场战争,但是仍然斗胆谈谈自己的看法。 所谓内存破坏漏洞,如其名,其最原始的作用就是对内存的破坏,这个破坏最开始可能是不可控制的。因此,攻击者需要把这种破坏转换为某种相对可以控制的成果。 在相对早期的对抗中,由于防护机制较少,攻击者会选择一些比较“肤浅”的方式利用内存破坏漏洞,比如说栈溢出破坏返回地址、破坏SEH。堆溢出破坏双向链表,来构造DWORD SHOOT(说白了就是一个write what where)。 而如今,简单的破坏已经不再凑效,攻击者就转而去寻找更值得被破坏的对象,比如说破坏掉数组的length、base来构造地址读写,或者破坏一些对象来构造一些write what where/ read write的原语。这个过程不一定是一步到位,攻击者通常需要一步一步的提高自己的能力,比如把一个write what where转换为一个可控的越界写,把越界写转换为任意地址读写。 我们也可以看到这是新兴的战场,攻击者不断的找到一些值得破坏的对象,而这些值得破坏的对象又一点一点的被防御方渐渐的禁掉了。比如Win10的TypeIsolation把一些容易构造原语的对象给隔离掉,javascriptcore把ArrayBuffer的DataStore隔离到一个指定区域,这一类对抗的例子可以说数不胜数,而且日益激烈,Win10 1903刚发现了一个好用的对象,1909就用不了了。 在传统的战场上,如GS、SafeSEH/SEHOP、DEP、ASLR、CFG、RFG等防护机制相继出现,虽然在这些防护机制的保护下,攻击者仍能一直不断攻击成功,但是也极大的提升了攻击者的门槛。 GS SafeSEH/SEHOP基本把利用栈溢出漏洞的可能性给封死了。为啥我敢说的这么绝对?栈跟堆不一样,堆上有趣的对象有很多,想破坏谁就把它堆风水一下就可以了。但是栈的布局相对固定,没办法风水,所以只要把有限个潜在的值得破坏的对象给封死,就万事大吉。 对于堆来说,情况相对复杂,DEP、ASLR、CFG、RFG在攻击成功的路上各设关卡,这些防御机制的存在逼迫攻击者必须构造出相对强大的能力才能够实现最终的目的(劫持控制流、篡改关键数据等),试想,如果没有ASLR和CFG,攻击者只需要一个read write,改掉vtable,配合一个xchg rax, rsp的gadget就可以一步到位劫持控制流和栈指针。这样的read write的原语对不少目标来说都不难构造。然而,有了这些防护机制之后,一些无法构造出强力的原语的目标和漏洞就变得难以利用,只有类似于脚本引擎、内核这种容易构造强力原语(如任意地址读写)的目标才能轻易打穿了。 在战争的后期大家发现,就算全保护机制全上了,对于能够构造出较强能力的攻击者,可以通过找到一些未被保护到的路径打穿目标。于是一方面防御方开始在这些目标外面套一层沙箱或者虚拟化并对其不断的完善,让这些目标即使被打穿也收益有限,这可以说又是另一个战场。另一方面就是防患于未然,即防止攻击者构造出较强的能力(如任意地址读写)。比如用对象隔离,来减少好用的对象,用内存分配随机化,增加攻击者将被破坏对象布局到指定位置的难度。我之前说的对象的新兴战场就是这一类,这些方法有时候很有效,但是如果漏洞品相好或者多个漏洞串联出很好的能力(即攻击者的初始能力就很强),这些方法也是有可能被绕过的。 现在自动化生成漏洞利用代码这个课题被研究的很火热。然而,大多数(尤其是国内)的研究都是把防御机制全下掉的情况下来自动生成利用代码。无防护机制的时代已经基本过去,因此这一类研究很难应用到实战中去,所以我个人觉得,根据现在的内存攻防形势,如果真要搞自动化漏洞利用的研究,我临时起意,感觉可以在以下几个点入手。

  1. 如何自动化找到某个目标中值得破坏的对象
  2. 如何自动化的将值得破坏的对象排布到漏洞所能触及的位置
  3. 如何自动化的串联多套不同的能力构造出任意地址读写
  4. 如何根据POC生成patch

我感觉这里面的一些课题是可做的,至少可以完成一些阶段性的目标。不过这些都是我的临时起意的想法,由于我们战队(r3kapig)后续可能会跟百度安全合作办自动化攻防的比赛,所以关于自动化攻防我后面也可能会单独开一篇仔细讨论。

0 人点赞