危险漫步博客
有时候,正是那些意想不到之人,成就了无人能成之事。
文章1443 浏览13839294

UAF本质论之漏洞是怎么形成的

UAF(Use-After-Free)类型的漏洞已经写了几期文章了,上一篇《UAF本质论》本意想作为点睛一笔,就此结束这个研究专题。没想外这篇小文居然得到一些挖洞大牛的关注,这让我觉得有点小意外和小得意,也听到了一些不赞同的声音,这让我发现虽然上篇只是一个系列的结尾,但当然不能强求每位同学都把整个系列读完,于是不能不把某些问题说透点明,这里还是以同一题目进行补充。

在上一篇文章里,我提出UAF类型漏洞的本质就是悬空指针的观点,但毕竟UAF是现在最火热的漏洞类型之一,特别是IE,几乎一多半都为UAF,成因居然被我归结为编程初学者最常犯的毛病,有些同学表示无论如何也不肯赞同。谦逊是一种美德,不过那是做人,我个人认为做学术是不得谦逊的,该坚持的还得坚持。后面我将分个两部分说说我的观点,欢迎继续炮轰。

本文是第一部分,先来谈谈漏洞的成因。这一次我们的视野更广阔一点,考察的对象不仅限于UAF,而是所有漏洞。我收集了近年的一些知名漏洞,经过整理分析,发现成因大致可以分为两类,一种为人为漏洞,一种为逻辑漏洞。第一种人为漏洞,是最常见的,也是最难接受的,说白了就是犯了本不该犯的低级错误,简称手抖。就以这两天非常火的幽灵漏洞来说吧。幽灵漏洞,CVE漏洞编号为CVE-2015-0235,影响了GNUglibc库的gethostbynam函数。就算不了解这个漏洞造成多大影响,了解网络编程的同学,也该知道gethostbyname函数是个多么底层多么常用的函数,考虑到这些,应该能大致猜想这个漏洞的严重性了。但这个漏洞的成因,概括来说就是在进行某次strcpy操作之前,确定大小时漏写了一个指针变量,于是导致缓冲区溢出。不知道别人的感觉,反正我看到gethostbyname函数爆出漏洞的第一感觉是非常震惊,但知道成因后却哑然失笑。太讽刺了对不对,影响面如此大的漏洞,起因竟如此低级,根本就是手抖了一下犯的错误。俗话说,功夫再高也怕菜刀,系统的安全性遵循木桶原理,再牛的系统,也永远是最低的那块木板决定了安全的水平。对于这个问题,我想再多说一点。我们都觉得能进大企业大公司,譬如微软公司,水平尤其编程水平一定特别的高,至少异于常人,于是连如何解微软的面试题目也有人专门出了一本书,还卖得特别火爆。可为什么微软家爆的漏洞也高得异于常人呢?我想,除了处于关注焦点之中外,还有一个重要原因,就是上面提到的木桶原理,这里,指的是人的木桶原理。开始挣血汗钱的码农们应该都有体会,就算是同一个人,在不同的心境、环境甚至同一天的不同时间,写代码的水平都会有波动,是不是十一点后达到峰值我不好下定论,但肯定再热爱这个行业的同学每个月也会有那么几天想要砸了屏幕逃出工位来一场说走就走的旅行。编程高手也是一样,产出低质甚至“弱智”的代码也不足为奇。当然了,高手犯低级错误还要通过一系列工业化检测最终流入成品中是一个概率极低的事件,但IT产品大爆炸必须依靠数以亿记的代码作为支撑,分母足够大了就算概率再小,分子也就是劣质代码量数量也会变得相当可观。再加上现在安全研究资源的增加和成长,所谓攻人之短,劣质代码引发的漏洞占了大头也实在不必大惊小怪了。其中就有一种叫指针悬空。

第二种逻辑漏洞,这个概念非常广,要讲清楚也不容易。如果说第一种漏洞是攻人之短,第二种漏洞就是以己之长了。早前有大牛称之为跨维攻击,袁哥提出的DVE技术,据说思路就是跨维攻击,用虚拟CPU执行exp,无论物理CPU加多少DEP防堵如何严密,只要将执行流转入虚拟CPU,就如入无人之境。什么叫跨维呢,大牛没多解释,我的理解是:出其不意。不意,就是没有意料到的意思,不是因为疏忽也不是因为疲惫,而是根本想不到竟会在这个地方翻船了。首先要说明的是,无论将信息安全的教科书或者论文集有多么厚实,实际上任何一套安全措施都是基于一些假设——也就是可能出现的攻击方向——建立而成的,因此,一旦这些假设并不是可能出现的攻击方向的全集,就可能出现跨维的漏洞了。说得比较绕口,举个例子,《三国演义》里面是特别喜欢用夜袭表示出其不意的,为什么呢?因为根据那时的技术条件,军事行动通常只能在日间进行,也就是假设攻防对抗只发生在日间,太阳落山以后就不设防了,于是一旦被夜袭自然就要送人头了有同学可能会说,这是因为那些将领太蠢没想到罢了,那好,再举一个聪明人的例子,毕达哥拉斯学派是数学史上非常有名的学派,就算不代表当时数学界最高水平也是之一,这个学派提出一个假设,就是任何一个数都可以表示成两个整数之比(也即有理数),请注意,这意味着当时数学界都假设所有数都是有理数,但实际上呢,当然不是,有理数并不是数的全集,外头还有无理数,这就使假设出现了漏洞。毕达哥拉斯对这个漏洞处置相当简单粗暴:他把发现者扔进海里喂鱼了。肯定有同学觉得这个场景离现在太远,其实不远,想想看,多少漏洞平台都有过“厂家认为不是漏洞”的回复,翻译过来就是,(厂家)我看到了,我也知道了,但经过我的逻辑思考后,并不认同这是漏洞。一般的解释是各方对安全的理解,或者称为假设,各有不同。但只要真的能被利用,那么厂家总是要吃上一些真金白银的亏,然后还得承认自己的逻辑假设是有误的。我特别想找一个有CVE编号的漏洞来具体说明,可是发现这很困难,这种逻辑漏洞更常见的表示形式其实是漏洞利用方法,也就是想出一种方法,让某个原本认为是正常,至多只是“有问题”,可能导致功能故障的代码变成漏洞。难就难在,不知道这个利用方法之前,这些代码都是“正常”代码,但一旦知道,就立即成了“漏洞”,而很难体现这个“变成”的过程。非要举一个例子的话,我选择去年十分火爆的Heartbleed漏洞,CVE编号CVE-2014-0160。这个漏洞大概可以概括为构造一个OpenSSL请求包让memcpy函数把SSLv3记录之后的数据直接输出。当然,出现问题的dl_both.C文件存在一点点判断问题,不过,能将这“一点点判断问题”和“输出用户密码”联系起来,使之成为重大安全隐患,绝对是一记神笔。大牛们常说,漏洞挖掘重在“猥亵”,这话说得懂的人都懂,不懂的人还是不懂,很玄妙。现在好一点了,大概可以将“猥亵”翻译为“开脑洞”,把看似不可能有关联的问题关联起来,这里再点一点题,就是想方设法突破固有的安全假设,找到一个让假设不成立的实例,让厂方的逻辑假设和现实冲突,最终突破之。

相关推荐