细说漏洞挖掘

聊聊漏洞分析、漏洞利用和漏洞挖掘。

前言

说到安全就不能不说漏洞,而说到漏洞就不可避免地会说到三座大山:

  • 漏洞分析

  • 漏洞利用

  • 漏洞挖掘

从笔者个人的感觉上来看,这三者尽管通常水乳交融、相互依赖,但难度是不尽相同的。本文就这三者分别谈谈自己的经验和想法。

漏洞分析

漏洞分析相对简单,通常公开的漏洞中就有一两句话描述了漏洞的成因,自己拉代码下来看也就能了解个大概。对于一些自己发现的bug,从崩溃日志中一般也能比较轻松地进行复现和调试。尽管有的bug排查起来相对繁琐,但总归是可以一步步减少范围锁定最终目标的。因此,网上对于漏洞分析的文章很多,一方面分析起来有迹可循,另一方面分析的漏洞也不一定是自己的“原创”漏洞,素材来源更加广泛。

漏洞分析虽然简单,却是每个安全研究人员的必经之路。就像练武中的扎马步、站梅花桩一样,是日积月累的基本功。之前研究内核时有段时间热衷于写漏洞分析的文章,后来随着日渐熟练,写文章记录的速度已经远远跟不上分析的进度,所以现在往往懒得动笔了。

基本功必不可少,但扎马步扎得再稳也不表示你能独步武林。有大佬曾经说过,如果他想的话,可以一天写好几篇分析文章还不带重样的。毕竟,漏洞分析的目的是为了学习、吸收、转化,以史为鉴,最终形成自己独到的理解。

漏洞利用

漏洞利用就相对复杂一点,尤其是对于二进制漏洞,成功的利用需要精巧的内存布局,因此需要对程序涉及到的数据结构要相当的了解。而且并不是所有漏洞都能转换为有效利用的,一般比较容易编写利用的漏洞,我们称之为品相好。对于品相不好的漏洞,我更喜欢将其称之为bug。当然也有人认为 bug 至少造成了程序崩溃,所以可以算一个DoS(拒绝服务)漏洞。

当然漏洞能否利用其实也是和人有关。对于复杂的系统,你认为无法利用的漏洞,大佬就能以一种你没想到的方式利用成功。比如安卓CVE-2019-2025(水滴)漏洞,属于Binder中的一个条件竞争,竞争窗口只有几条汇编指令。漏洞品相相当不好,连CVSS给出的可利用分数(Exploitability Score)也只有1.8分,但360的大佬们也通过玩弄调度器进行稳定利用提权了。

因此,关于漏洞利用的文章也就少了很多。一方面处于负责任披露安全问题的考虑,安全研究人员不会给出完整的利用细节,以免脚本小子滥用;另一方面对于公开的利用,你也总不能跟着写一篇文章灌水,毕竟利用思路很多时候是因人而异的,过于雷同就难免有炒冷饭的嫌疑,除非有一些独到的思考补充,或者有新的利用思路。

很多时候漏洞利用的文章看着看着就变成了漏洞利用分析的文章,这也说明了漏洞利用难度颇高,能独立写出原创利用并进行分享的人不多。就我的感觉而言,漏洞利用更像是另一种形式的软件开发,首先通过漏洞构造原语,然后通过原语实现最终的利用程序。

漏洞挖掘

漏洞挖掘可以说是安全研究人员向往的高地之一,不管你分析了多少漏洞,写了多少利用,如果你没有自己挖掘出过原创的漏洞,那你的安全研究生涯就是不完整的。但是漏洞挖掘这事儿并不是确定性的。漏洞分析只要有漏洞肯定能分析清楚,只不过是时间问题;漏洞利用只要不是明显的无法利用,那至少也存在利用成功的可能性。

漏洞挖掘则不然,即便你盯着某个应用使劲挖,也不能保证有结果,说不定对方根本就没有能触发的漏洞。都说世上没有绝对安全的系统,但是相对安全的系统一抓一大把,至少在出问题之前,你是不知道的。

我们能看到各种安全会议中介绍各种新发现的漏洞和问题,网上也有很多相关的文章,但更多是炫技式分享(show-off),很少有分享怎么挖洞的。因此笔者就先抛砖引玉,谈谈自己的想法。

Fuzzing

自从 AFL 横空出世之后,当今漏洞挖掘言必称 Fuzzing,仿佛这是李云龙他娘的意大利炮,不管三七二十一先来上一发就能轰出几个 0day。当然,我不是说 Fuzz 不好,只不过凡事都有其诞生和得以应用的环境。

Fuzzing 即模糊测试,在早期是 QA 测试中的一项黑盒测试技术,通过随机变异的输入来测试程序的鲁棒性。在程序的崩溃被用于漏洞利用后,也就一跃成为一种漏洞挖掘方法。随机变异输入的效率相对低下,可能变异了半天连 main 函数里第一个 if 都没有跳进去。AFL 率先提出并实现了根据路径/覆盖率等反馈来进行输入的变异,从而大大提升了测试用例的有效性。

细说漏洞挖掘_第1张图片

AFL

自从 2013 年 AFL 提出以来,各类 Fuzzer 百花齐放,在学术上有了爆发性的论文增长;开源社区有 honggfuzz、libFuzzer 等优秀的项目;在工程上有 OSS-Fuzz 利用庞大机器集群进行持续测试的应用和 syzkaller 这种年均发现几千内核漏洞的工具等。

从产出的漏洞数量来看,Fuzzing 作为一种漏洞挖掘方法可谓一骑绝尘。当时,随着时间的推移,通用模糊测试策略已经越来越难发现新的漏洞,要么你有独特的测试语料,要么你有领先的运算资源。因此,一部分人就从通用 Fuzzer 转回到了针对特定目标变异的 Fuzzer(即 Structure Aware Fuzzer)。也就是说,只针对目标程序接受的数据类型进行特定变异,比如针对 PDF 文件格式每个字段变异等等。

别忘了,AFL 这种通用 Fuzzer 的出现,就是为了实现一次编码,到处 Fuzz 的目的;而针对不同目标去写 Fuzzer,显然有违初衷。另外,如果目标接受的是已知格式的输入还好,对于未知格式,还需要自己去分析和理解各个字段含义。在阅读代码和理解代码逻辑的过程中,目标程序的潜在问题很可能已经出现在你眼前了,再去编写一个不能复用的 Fuzzer,显得有些多此一举。这种发现漏洞的方法也就是下节所说的——代码审计。

代码审计

代码审计,俗称看代码。有的人用 SourceInsight 看,有的人用 VIM 看,但不管怎么样还是用眼睛看。既然大家都长了两只眼睛,为什么有的人就能一个月看出十几个高危,有的人就只看了个寂寞?

看代码也是有方法的。虽然我比较想听听 @oldfresher 是怎么看代码的,但他似乎不太愿意分享,所以我只能说说自己的方法。

要挖漏洞首先要对漏洞进行分类,大致可以分为下面三种:

  • 设计漏洞

  • 实现漏洞

  • 操作漏洞

所谓设计漏洞就是软件设计过程中就存在逻辑问题,比如 WiFi 的 WEP,设计的问题往往是比较严重的,而且修复周期长,所幸这类问题不是太多;实现漏洞就是我们常见的软件漏洞,内存溢出、UAF、条件竞争等都算在里面;操作漏洞和实现漏洞往往类似,只不过更多是指配置错误而产生的漏洞,比如 nginx 配置错误导致的目录穿越问题就属于一种操作漏洞。

明确漏洞类型后也不是马上开始看代码,而是先进行初步的攻击面分析,也就是常说的威胁建模。主要分为下面几步:

  • 信息收集: 收集所有相关的资料,尤其是设计文档或者帮助手册等

  • 应用架构建模: 列举应用所含的组件以及状态机,注意各个组件之间隐含的信任关系

  • 威胁鉴定: 在各个流程中列举潜在的攻击点,并分别标记危害等级

  • 审计计划: 按优先级对实现的审计计划进行排序

代码审计听起来是个让人退缩任务,因为你面对的是一堆你不熟悉的代码,而且要求你快速地建立起自己的理解而且找到其中最深层的秘密(安全漏洞)。通常你不会有足够的时间审计项目的每一行代码,因此这其中的一个重点就是懂得如何分配精力,在最可能出现安全问题的代码中达到满意的审计覆盖率。

成功的代码审计过程一定是务实、灵活且面向结果的。虽然讲究方法,但并不意味着根据别人的方法就能成功。与很多人的认知不同,代码审计其实是一件需要创造力的技能。那位说了,看别人代码要什么创造力?要在应用中找到漏洞,审计者需要将自己代入作者的思维中理解代码,同时还需要跳出作者的思维,洞察到原作者没有预料到的可能性;这种技能与知识相对,像是骑车、游泳、弹琴一样,是需要通过学习和练习去掌握的,而一旦掌握就像本能的一部分难以忘记。当然代码审计也有知识的部分,比如需要了解各种漏洞类型和场景等。

这些都这只是代码审计中的冰山一角,篇幅原因无法面面俱到。比如代码审计策略的抉择,是深度优先还是广度优先(看到某个函数调用是否需要追进去看);以及使用现代的静态分析工具来辅助审计,比如 Fority、CodeQL 等,后续有时间再单独进行介绍吧。

后记

漏洞分析是技术,漏洞利用是艺术,漏洞挖掘是法术。关于漏洞利用和漏洞挖掘哪个“技术含量”更高,还存在一定争议,但漏洞分析的基础地位毫无疑问。技术可以学,艺术可以练,法术呢?其实同样也可以通过练习提高自己的 漏洞挖掘水平。推荐一个忘了是什么地方的议题中提供的方法(也许是 CCC):

  1. 找到公开的漏洞通告,根据标题的内容自己去相关模块中审计看是否能发现该漏洞

  2. 如果发现不了,就回头接着看漏洞通告的细节,反思自己的审计方法

  3. 不断重复,直到让自己可以认为找漏洞只是时间问题而不是能力问题

       网络安全入门学习路线

其实入门网络安全要学的东西不算多,也就是网络基础+操作系统+中间件+数据库,四个流程下来就差不多了。

1.网络安全法和了解电脑基础

其中包括操作系统Windows基础和Linux基础,标记语言HTML基础和代码JS基础,以及网络基础、数据库基础和虚拟机使用等...

别被这些看上去很多的东西给吓到了,其实都是很简单的基础知识,同学们看完基本上都能掌握。计算机专业的同学都应该接触了解过,这部分可以直接略过。没学过的同学也不要慌,可以去B站搜索相关视频,你搜关键词网络安全工程师会出现很多相关的视频教程,我粗略的看了一下,排名第一的视频就讲的很详细。 当然你也可以看下面这个视频教程仅展示部分截图: 学到http和https抓包后能读懂它在说什么就行。

2.网络基础和编程语言

3.入手Web安全

web是对外开放的,自然成了的重点关照对象,有事没事就来入侵一波,你说不管能行吗! 想学好Web安全,咱首先得先弄清web是怎么搭建的,知道它的构造才能精准打击。所以web前端和web后端的知识多少要了解点,然后再学点python,起码得看懂部分代码吧。

最后网站开发知识多少也要了解点,不过别紧张,只是学习基础知识。

等你用几周的时间学完这些,基本上算是具备了入门合格渗透工程师的资格,记得上述的重点要重点关注哦! 再就是,要正式进入web安全领域,得学会web渗透,OWASP TOP 10等常见Web漏洞原理与利用方式需要掌握,像SQL注入/XSS跨站脚本攻击/Webshell木马编写/命令执行等。

这个过程并不枯燥,一边打怪刷级一边成长岂不美哉,每个攻击手段都能让你玩得不亦乐乎,而且总有更猥琐的方法等着你去实践。

学完web渗透还不算完,还得掌握相关系统层面漏洞,像ms17-010永恒之蓝等各种微软ms漏洞,所以要学习后渗透。可能到这里大家已经不知所云了,不过不要紧,等你学会了web渗透再来看会发现很简单。

其实学会了这几步,你就正式从新手小白晋升为入门学员了,真的不算难,你上你也行。

4.安全体系

不过我们这个水平也就算个渗透测试工程师,也就只能做个基础的安全服务,而这个领域还有很多业务,像攻防演练、等保测评、风险评估等,我们的能力根本不够看。

所以想要成为一名合格的网络工程师,想要拿到安全公司的offer,还得再掌握更多的网络安全知识,能力再更上一层楼才行。即便以后进入企业,也需要学习很多新知识,不充实自己的技能就会被淘汰。

从时代发展的角度看,网络安全的知识是学不完的,而且以后要学的会更多,同学们要摆正心态,既然选择入门网络安全,就不能仅仅只是入门程度而已,能力越强机会才越多。

尾言

因为入门学习阶段知识点比较杂,所以我讲得比较笼统,最后联合CSDN整理了一套【282G】网络安全从入门到精通资料包,需要的小伙伴可以点击链接领取哦! 网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

你可能感兴趣的:(安全)