初学者最好不要直接上手进行漏洞挖掘,因为漏洞挖掘需要大量的系统基础知识和理论做铺垫,且难度较大。
较合理的途径是从漏洞利用入手,分析一些公开的 CVE 漏洞。许多漏洞都有详细的资料,分析研究多了,对漏洞的认识自然会加深,然后再去搞挖掘就会易上手一点。
俗话说:'磨刀不误砍柴工',就是这么个理儿。
对于有一些基础知识的初学者,应该怎样进行漏洞挖掘呢?
一、漏洞是怎样被发现的
从某个角度来讲,我们可以将漏洞挖掘工作比作玩迷宫游戏,不同的是,这个迷宫与我们平时所见的游戏中的迷宫略有不同:
- 你无法立即看到它整体的外观
- 随着漏洞挖掘工作的深入,这个迷宫的形状逐渐扩大
- 你将会拥有多个起点及终点,但是无法确定这些点具体在哪里
- 最终这个迷宫可能永远也无法 100% 的完整,但是却能够弄清楚 A 点至 B 点的一条完整路径
具体一点地描述,我们可以将漏洞挖掘工作归结为三个步骤:
- 枚举程序入口点(例如:与程序交互的接口)
- 思考可能出现的不安全状态(即漏洞)
- 设法使用识别的入口点到达不安全状态
即是说,在这个过程中,迷宫是我们研究的应用程序,地图是我们对程序的理解程度,起点是我们的入口点(交互接口),终点为程序的不安全状态。
所谓入口点,既可以是 UI 界面上直观可见的交互接口,也可以是非常模糊与透明的交互接口(例如 IPC),以下是部分安全研究员较为感兴趣的关注点:
- 应用程序中比较古老的代码段,并且这一部分随着时间的推移并没有太大的变化。
- 应用程序中用于连接由不同开发团队或者开发者开发的程序模块的接口部分
- 应用程序中那些调试和测试的部分代码,这部分代码本应在形成 Release 版本时去除,但由于某些原因不小心遗留在程序中。
- C-S 模式(带客户端和服务端)的应用中客户端及服务端调用 API 的差异部分(例如网页表单中的 hide 属性字段)
- 不受终端用户直接影响的内部请求(如 IPC)
从攻击面上来划分,可以将漏洞分为两大类,通用漏洞(General)和上下文漏洞(Contextual)。通用型漏洞是指在我们对应用的业务逻辑不是非常熟悉的情况下能够找出的漏洞,例如一些 RCE(远程代码执行)、SQLi(sql 注入)、XSS(跨站)等。上下文漏洞是指需要在对应用的业务逻辑、认证方式等非常熟悉的情况下才能找到的漏洞,例如权限绕过等。
在漏洞挖掘的过程中,首先根据经验优先考虑研究那些可能会对应用产生巨大威胁的部分。一些轻量级威胁检测模型(如 STRIDE)可以辅助我们做出这样的决策。STRIDE 模型包括:欺骗(Spoofing)、篡改(Tampering)、抵赖(Repudiation)、信息泄露(Information Disclosure)、拒绝服务(Denial of Service)、权限提升(Elevation of Privilege)。
下面我们来看一个 WEB 应用程序的漏洞示例,后面将会介绍桌面程序:
首先我们假设目标 web 应用是一个单页面应用程序(single-page-application SPA),我们已经获得合法验证去访问这个应用,但是我们没有任何关于服务端的源代码或者二进制文件。在这种情况下,当我们枚举入口点时,可以通过探寻该应用的不同功能来进一步了解其业务逻辑及功能,可以通过抓包分析看 HTTP 请求内容,也可以分析客户端的网页代码获取需要提交表单的列表,但是最终的限制还是我们无法具体知悉客户端和服务端调用的 API 之间的区别,不过通过以上方法,我们可以找到一些入口点。
接着就是操作这些入口点,以试图达到我们预期的不安全状态。由于漏洞的形态很多,我们通常需要构建一个适用于该测试应用程序的业务功能漏洞的测试集,以求达到最高效地寻找漏洞。如果不那样做的话,我们就将会在一些无用的测试集上花费大量时间,并且看不到任何效果(举个例子,当后台的数据库为 Postgres 时,我们用 xp_cmdshell 去测试,测试再多次都无济于事)。所以在构造测试集时,需对应用程序的逻辑有较深的理解。
对于桌面应用程序,漏洞挖掘的思路本质上与 web 程序是类似的,不过也有一些区别:最大的区别在于,桌面应用的执行方式与流程与 web 程序不一样。桌面应用通常涉及本地文件系统访问、注册表操作、进程间通信等,攻击面更偏向于内存管理和本地权限控制。
与黑盒测试相比,当有源代码时(白盒测试),在寻找代码入口和程序执行路径等漏洞挖掘点时所做的猜测性的工作会大大减少,在这种情况下,将数据载荷从入口点执行到不安全的程序位置的效率低于从不安全的程序位置回溯至入口点。不过在白盒测试中,你对代码的测试的覆盖面可能会由于你自己的知识局限性而受到影响。
二、漏洞挖掘需要具备的知识
从事漏洞挖掘工作需要具备的知识是极其广泛的,并且随着时间在不断改变,也取决于你所研究的对象(web 程序、桌面程序、嵌入式等等)。不过,万变不离其宗,所需要掌握的知识领域却总可以认为是确定的,大致可以分为以下四个方面:
- 程序正向开发技术。这是一个开发者需要掌握的能力,包括编程语言、系统内部设计、设计模式、协议、框架等。拥有丰富编程经验与开发能力的人在漏洞挖掘过程中往往比那些只对安全相关领域有所了解的人员对目标应用能有更深入的理解,从而有更高的产出。
- 攻防一体的理念。这些知识涵盖了从基本的安全原则到不断变换的漏洞形态及漏洞缓解措施。攻击和防御结合的理念,能够有效帮助研究者既能够发现漏洞,同时也能够快速给出有效的漏洞缓解措施和规避方法。


