初学者最好不要直接上手进行漏洞挖掘,因为漏洞挖掘需要大量的系统基础知识和理论做铺垫,且难度较大。
较合理的途径是从漏洞利用入手,分析一些公开的 CVE 漏洞。许多漏洞都有详细的资料,分析研究多了,对漏洞的认识自然会加深,然后再去搞挖掘就会易上手一点。
俗话说:'磨刀不误砍柴工',就是这么个理儿。
漏洞挖掘是将应用程序比作迷宫,通过枚举入口点并寻找不安全状态的过程。文章介绍了发现漏洞的三个步骤、所需的知识体系(开发技术、攻防理念、工具使用、应用理解)以及四种分析模型(用途、执行条件、通信、代码二进制)。强调白盒与黑盒测试的区别,指出现代利用往往依赖漏洞链而非单一漏洞,并提倡在团队中保持坦诚与高效学习。

初学者最好不要直接上手进行漏洞挖掘,因为漏洞挖掘需要大量的系统基础知识和理论做铺垫,且难度较大。
较合理的途径是从漏洞利用入手,分析一些公开的 CVE 漏洞。许多漏洞都有详细的资料,分析研究多了,对漏洞的认识自然会加深,然后再去搞挖掘就会易上手一点。
俗话说:'磨刀不误砍柴工',就是这么个理儿。
对于有一些基础知识的初学者,应该怎样进行漏洞挖掘呢?
从某个角度来讲,我们可以将漏洞挖掘工作比作玩迷宫游戏,不同的是,这个迷宫与我们平时所见的游戏中的迷宫略有不同:
具体一点地描述,我们可以将漏洞挖掘工作归结为三个步骤:
即是说,在这个过程中,迷宫是我们研究的应用程序,地图是我们对程序的理解程度,起点是我们的入口点(交互接口),终点为程序的不安全状态。
所谓入口点,既可以是 UI 界面上直观可见的交互接口,也可以是非常模糊与透明的交互接口(例如 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 程序、桌面程序、嵌入式等等)。不过,万变不离其宗,所需要掌握的知识领域却总可以认为是确定的,大致可以分为以下四个方面:
下面表格介绍了挖掘 web 应用程序和桌面应用程序的漏洞时所需要掌握的内容。每个类别中的条目仅用于说明目的,并非详尽无遗。
| 领域 | Web 应用重点 | 桌面应用重点 |
|---|---|---|
| 网络协议 | HTTP/HTTPS, WebSocket | TCP/IP, UDP, Local IPC |
| 数据存储 | SQL, NoSQL, Session | Registry, File System, Memory |
| 输入验证 | 参数过滤,WAF 绕过 | 缓冲区溢出,格式化字符串 |
| 身份认证 | JWT, OAuth, Cookie | Token, Credential Dumping |
这些知识领域将会帮助你提高挖掘漏洞的能力。如果说上面一节是讲诉挖掘漏洞所需要的知识,那么下面的这一节将讲诉挖漏洞如何做。
当分析一个应用程序时,你可以使用下图展示的四个'分析模型',如果遇到障碍导致思路受阻时,你可以从其中一个模型切换到下一个模型,当然,这不是一个线性的切换,你也可以有自己的一套方法。
程序用途分析是指理解一个应用程序做了什么工作,会提供什么服务等。同时,阅读与该程序的相关文档将有助于进一步理解程序功能。这样做有利于对程序有一个透彻的了解。
或许,比起直接构造测试样例进行测试,这项工作可能并不是那么有意思。不过,它的确可以节省一大笔时间。举一个例子,Oracle Opera(一个广泛使用的酒店管理软件)CVE-2016-5563/4/5 的远程代码执行漏洞,可以通过阅读器用户手册快速找到可能存在危险的数据表,最后快速找出远程代码执行漏洞。
执行条件分析是指理解应用程序运行时需要包括的环境因素,比如网络配置,端口使用等。可以通过端口扫描,漏洞扫描等方式进行操作。这些配置上的问题,很可能就会导致一个漏洞的出现。
举个例子,一个系统权限级别的程序,由于配置错误,可能会使的低权限的用户能够访问并修改,最终导致一个权限提升,引发一个提权漏洞。又比如,在一个网络程序中,可能程序本身并没有错误,但是由于这个服务器开了一个 anonymous 的 FTP 服务器,那么任何人都有可能访问这个机器,这就导致 web 应用的源代码或者其他敏感文件暴露在外面。这些问题,理论上并非程序自身的漏洞,但是由于其执行环境的因素,就使得其成为一个漏洞。
通信分析是指对一个目标程序与其他进程或系统之间交互信息的方式进行深入分析。在这样的前提下,可通过发送精心构造的请求(Request)等方法,触发不安全状态。许多 web 应用程序漏洞都是通过这种方式发现的。
在上述模式下,需要我们对数据通信协议有较为清晰的认识,如果并不能够清晰的了解协议格式呢?这种情况就要借助黑盒测试的技术进行解决,主要通过发送请求,并根据返回值进行判断是否存在异常。
下面举个例子来说明,这里假设存在一个金融网站,里面有一项功能允许用户使用不同的货币购买预付信用卡。这里假设实现这项业务的请求(Request)如下:
当我们要去测试这样一个应用程序时,首先我们可能会想到发送一个正常的数据请求,以帮助我们了解该应用程序的标准响应的格式。例如下图,用 CAD 去购买 82 美刀的预付卡的请求和响应是下面这个样子:
[此处省略图片,实际应替换为文字描述]
或许我们并不知道程序在后台到底对我们的数据做了何种处理,但是我们通过观察 status 字段的属性知道我们的请求是 ok 的,下面如果我们将 fromAmount 参数调整为一个负数,或者将 fromAccount 调整为其他某个人的账户,那么这个 web 应用就可能会返回错误响应,比如验证不通过。另外如果我们将 currencyPair 从 CADUSD(加元对美元)改为 CADJPY(加元对日元)而 cardType 不变,那么我们会看到返回值中 toAmount 字段从 82.20 变为 8863.68。如果程序缺乏足够的验证的话,我们有可能通过这种方式获取到更多的钱而付出的钱不变。
另一方面,如果我们能够获取到后台代码或程序,那事情就变得更加有意思,我们可以轻松了解到后台的运作流程,如后台是如何处理请求,有哪些错误响应,这将有助于我们构造出更加具有针对性的数据对应用进行测试。
代码及二进制分析是指理解一个目标程序是如何处理用户输入的数据,以及该程序的执行流程。目前有很多方法可以对程序实现动态和静态分析,下面介绍其中一部分:
在这个过程中,动态分析和静态分析需要紧密配合起来。举个例子,当你在寻找如何从 A 点走到 B 点时,静态分析就好比是在阅读一张地图,而动态分析就好比直接在这地图上走,需要实时关注路上的天气及交通状况,IDA 和 windbg 的配合就是如此。静态分析可以对程序有一个全貌但不细致的理解,动态分析则可以对程序有一个狭隘但却细致的理解,二者是相互补充的。
外部引用分析。在分析程序的过程中,程序上下文环境中可能非常有限,这个时候分析程序的导入 API 可以帮助我们进一步了解程序的功能以及它与操作系统的交互方式。比如说,程序引用加密库对数据进行加密,那么你可以跟踪这个加密库并分析其功能,进而分析自己的输入是否能够影响其功能。另外,理解程序是如何与操作系统的交互也可以帮助我们进一步找到与程序进行交互的入口点。
字符串分析,与外部引用分析一样,分析程序中的字符串将帮助我们进一步理解程序中的功能,特别是那些调试信息,关键字或者令牌什么的,或者是那些看起来特别奇特的东西,对这些关键的字符串的分析及跟踪也将有利于我们寻找到更多的程序入口,进而更加全面的找出程序中的缺陷。
安全扫描分析。使用自动化的扫描工具(如 PHP 源代码扫描 AWS)可能帮助我们快速找到一些常见的漏洞。但是对于寻找基于上下文和基于设计的漏洞并没有太大帮助。这种方法可以用来做一些辅助性的功能,如果单纯靠扫描就能找出一堆漏洞,你研究的目标安全做的就太差了,这在目前并不常见,或者说研究这类目标对于提高你自己并无太大的帮助。
依赖性分析。一个应用程序往往会依赖其他外来的组件,比如一些开源模块,它所依赖的开源模块自身存在的漏洞可能会被引入造成自身的未公开漏洞。值得一提的是,现今一个程序往往都是引用了众多第三方扩展模块,这些第三方的漏洞极易造成主程序的漏洞。举个例子,大多数浏览器都会使用 sqlite 做数据缓存,如果 sqlite 存在漏洞,那么这些浏览器都有可能存在问题,无论是谷歌还是火狐。
版本分析。如果你有机会访问程序的代码仓库,那么你就可以通过分析历史版本的方式对程序进行分析,这种方式不是基于上下文的,比如说,寻找那些长时间没有做改动的部分,这些部分极易寻在漏洞。
代码分析通常需要花费比其他方式更多的时间,同时也更难,因为研究者对这个程序的功能和使用的技术的掌握程度要不亚于其开发者,另外,一个程序的开发可能是由一个团队进行维护,那么对于研究者,全面掌握这些东西显得比较困难。但是只要肯专研,其实什么也都是能够克服的,请参考名言:只要工夫深,铁杵磨成针。
另外,不得不再次强调一下编程能力的重要性,如果一个研究人员对他当前研究的程序所采用的语言和技术有深入扎实的功底,那么他必将创造出很多有价值的东西。从攻击的角度来说,他可以发现更加简单及直观的漏洞,编写利用程序也将得心应手。从防御的角度来说,他可以提供出代码级别的、具有高度针对性的修复建议而非那种通用的方法。
漏洞的复杂性分布非常广。一方面,有很多漏洞非常简单与直观,并且利用代码一目了然,比如说经典的 sql 注入。另一方面,在系统中有的看似并不相关,并且就其自身而言并非不安全,但是当这些东西以一种特定的方式结合起来的时候,就有可能引发大的漏洞,比如说条件竞争,或者一些其他的复杂的逻辑漏洞。可以尝试将这些漏洞按照复杂级别分为'一级漏洞'和'二级漏洞',不过也有其他分类方法。引用一局来自 Project Zero 的 Ben Hawkes 说过的一句话:
"The modern exploit is not a single shot vulnerability anymore. They tend to be a chain of vulnerabilities that add up to a full-system compromise."
如今想要完成一个完整的利用,只靠单一的漏洞往往行不通。很多时候我们需要靠一连串的漏洞才能完成一起完整的利用,致使系统'妥协'。
在一个团队中工作能够有效帮助自己了解自己不知道的知识,以及提高自己已知的知识。不过在团队中要需要注意工作的方式方法,知之为知之,不知为不知,永远不要强行假装精通你不熟悉的东西,因为精通的人可以很轻易的指出你的症结。如果一个团队里面大家都不坦诚相待,那么这不是一个合格的团队,你可以尽早更换。在优秀的团队中,不要指望别人会把所有的知识交给你,要学会如何高效的学习,并在团队交流与合作中不断提高。
漏洞挖掘是一项高风险高回报的技术活动,必须在法律允许的范围内进行。在进行任何测试之前,请务必获得授权。未经授权对他人系统进行测试可能触犯法律。
建议初学者通过合法的渠道练习,例如参与 CTF 比赛、在 HackerOne 或 Bugcrowd 等平台提交漏洞报告。持续学习新的漏洞类型和防御技术,保持对新技术的敏感度。
此外,建立自己的知识库,记录挖掘过程中的思路和技巧,有助于长期的成长。记住,安全是一场持久战,需要耐心和毅力。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online