Q: 如何挖掘漏洞?
A: 首先得强调一下,这是一个相当高水平的问题。因为从问题中我们看不出提问者感兴趣的是哪种技术。更重要的,我们并不清楚我们正在讨论的是关于一个想要在定期的全网渗透测试中找出的系统漏洞(即因配置不当或者在已安装的服务中存在未修复的漏洞),还是关于在一个应用、服务、驱动/内核模块、操作系统、防火墙等发现未知的漏洞。由于本人侧重的不是漏洞研究而是渗透测试,故在此假定我们讨论的是渗透测试。
个人认为有以下三类方法:
- 代码审查(包括那些必须通过逆向才能得到的代码)
- 黑盒测试(包括使用一些自动化工具,例如 scanners、 fuzzers 等)
- 文档研究
上述方法均有一些前提条件和局限性,对此漏洞行之有效并不代表对彼漏洞也是行之有效的。事实上,不存在一种对所有漏洞都适用的完美方法——我所说的通常都是针对特定目标而言。还有,上述方法通常都是混合使用的。
1. 代码审查
前提条件:
了解给定技术漏洞分类知识和通用漏洞分类知识
[对于二进制目标] 逆向工程技术
优点:
缺点:
漏洞类别是指一种漏洞所被熟知为哪种类型。例如,栈溢出、XSS 注入、SQL 注入等。有些安全漏洞是由许多问题同时导致的(最常见的例子就是由整数溢出导致的栈溢出)。需要注意的是,并不是所有已经被发现(且已公布)的漏洞都被明确归类——你可能会遇到面向特定应用或者面向特定技术的漏洞,它们并不属于任何常见的漏洞类型。如想详细了解,请看 Common Weakness Enumeration (MITRE),Adversarial Tactics, Techniques & Common Knowledge (MITRE) 和 OWASP Periodic Tables of Vulnerabilities 。
常规思路就是分析代码,找出代码的逻辑错误和一些经典的漏洞(例如 XSS 注入、栈溢出、ACL 错误等)。这种方法基本上和研究员一样——如果失去耐心(对代码只是粗略地浏览而不是试图真正理解)或者对出现的漏洞类型不清楚,就很可能与漏洞擦肩而过。
这种方法从真正意义上讲适用范围不广——项目越小,对整个代码进行审查就越容易。但是代码越多,就越难以准确地给出真正有趣的代码片段(通常我们希望漏洞最有可能出现的地方,例如协议/文件的格式化解析、用户输入等)。
2. 黑盒测试
前提条件:
优点:
缺点:
[自动化黑盒测试] scanners / fuzzers 都是很好的工具,但是它们能力有限,对于大多数复杂的漏洞束手无策。
[手工化黑盒测试] 比代码审查所花费的时间少,但是不如自动化黑盒测试适用范围广。
[手工化黑盒测试] 取决于研究员的想象力(即这种方法很难发现一些高级的漏洞)。
这种方法注重的是通过和应用交互,观察其输出,而不是像代码审查那样从内部代码着手。
对于 Web 应用,通常我会优先使用手工化黑盒测试的方法,因为这样可以对目标程序有一个整体上的了解。
自动化黑盒测试使用范围很广。根据我的经验,一边配置好 scanners / fuzzers 让其在后台自动测试,一边进行手工测试是一个很好的方式。同时别忘了对你的发现进行复查——这一点取决于所使用的技术和工具,因为可能有许多误判或重复。还有一点,这些工具通常只对一些特定类型的漏洞有效。
3. 文档研究
前提条件:
程序员经验或者了解程序员的思考方式
了解给定技术漏洞分类知识和通用漏洞分类知识
优点:
缺点:
取决于研究员的想象力
只关注系统的单个协议/格式/部分
常规思路是对该程序的文档/说明书/参考手册进行研究,找出程序员在实现功能时可能会理解有误的地方。和代码审查和黑盒测试相比,这种方法直到后期才会和被测试的程序有交互。请看以下例子:
一段官方说明文档:
此程序输出为变量长度,该变量从 <code size>+1 位开始,共取 12 位。
有些(心情不好或者缺少经验的)程序员可能会认为不必对该变量进行检查——变量长度肯定小于等于 12 位(4096)。
然而,正确的理解应为:
检查变量是否小于等于 4096,否则就可能会出错。
这是一个真实案例,请看 GIF 说明书 ,与此有关的漏洞已经被爆出来了。
发现这一点后,攻击者通常会精心构造一堆违反说明文档的输入,然后利用它们对给定功能(或其它功能)进行测试,检查是否会触发某种错误,还可以选择针对特定代码片段进行审查,看看程序员是否对此做出了应对措施。
在某些情况下,如 Mateusz ‘j00ru’ Jurczyk 和 James Forshaw 所展示的,此漏洞可被利用为自动浏览文档。
最后注意
不要认为一旦你发现了一个漏洞,这件事就完了。通常来讲,整个工作可遵循以下步骤:
[前提条件] 发现一个可能的漏洞
[通常不需要黑盒测试] 编写一个确保可以触发该漏洞的恶意代码(因为后期有时候可能由于某些原因,又无法触发该漏洞了)
编写一个概念证明性恶意代码证明该漏洞的实际影响(它真是一个代码执行吗?或者由于某些原因,可能它只是一个拒绝服务而已)
[可选] 在渗透测试期间,通常要编写一个武器化恶意代码(生成一个 shell ,控制对进程的破坏等)
还有,并非所有漏洞都是安全漏洞。按照经验:
安全漏洞的影响范围会超出问题代码所在片段
非安全漏洞的影响仅局限于问题代码所在片段
另外值得注意的是,安全漏洞的影响并不总是毁灭性的(提示:当报告漏洞时,别过分夸大其词)——还有很多需要考虑的事情,例如漏洞的威胁程度(假设最糟糕的情况,一个富有经验的黑客可以利用该漏洞做出多大破坏?)和可利用等级(例如,会有人对这个漏洞感兴趣吗?执行一次成功的攻击的代价有多大?)一个典型的高安全性、高风险的漏洞是隐藏于 Apache Web 服务器上面的很稳定的远程代码执行漏洞。与此相反,另一个低安全性、低风险的漏洞是通过 XSRF (跨站请求伪造)改变一个 10 人使用的 Web 框架中的 UI 界面语言,该漏洞需要猜一个 16 位的数字(的确,攻击者是可以选择这么做,但是有什么意义吗?)。对于初级研究员(包括当初的我)来说很容易犯的一个错误就是将每个漏洞都宣称为是高安全性、高风险的,事实显然并非如此。
现在可以对上面那个高水平的问题给出一个高水平的回答了。
从学习漏洞分类开始,具体到你最感兴趣的技术(当然了,要及时扩展到其他技术和通用漏洞分类),然后用上面介绍的方法试试。别害怕这会花费大量时间——即使是很优秀的研究员也可能花费几周的时间而一无所得(但是在这个过程中总能学到些知识),所以别总想着用几个小时就找出一个好漏洞。
原文链接:How to find vulnerabilities?
本文由 看雪翻译小组 hesir 编译
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)