导语:在分析一个应用程序时,我使用了下面的四种“分析模式”,每当我遇到困难时,就不断地从一种模式切换到另一种模式。这不是一个线性或周期性的过程。我不确定这个模型是否详尽无遗,但确实可以帮助我保持跟踪覆盖面。
执行什么活动?
在分析一个应用程序时,我使用了下面的四种“分析模式”,每当我遇到困难时,就不断地从一种模式切换到另一种模式。这不是一个线性或周期性的过程。我不确定这个模型是否详尽无遗,但确实可以帮助我保持跟踪覆盖面。
在每种模式下都有主动和被动的活动。主动活动需要与应用程序或其环境进行某种程度的交互,而被动活动则不需要。也就是说,划分的边界并不总是清晰的。每个活动的目的如下:
1. 理解有关安全性的假设。
2. 假设如何破坏他们。
3. 试图破坏他们。
用例分析是指了解应用程序做了什么,以及它服务的目的。这通常是我负责新应用程序时要做的第一件事。与应用程序的工作版本交互以及读取一些高级文档有助于巩固对其特性和预期边界的理解。这有助于更快地生成测试用例。如果我有机会要求内部文档(威胁模型,开发人员文档等),我总是会试图这样做,以便得到更透彻的理解。
这可能不如深入探索测试用例那样有趣,但它为我节省了大量的时间。我可以讲的一个例子就是Oracle Opera,通过阅读用户手册,我能够快速找出哪些数据库表存储了有价值的加密数据(而不是一一浏览)。
实现分析是了解应用程序驻留的环境。这可能包括在被动级别检查网络和主机配置,并在主动级别执行端口或漏洞扫描。
这种示例可能是一个安装的系统服务的可执行文件具有ACL,允许低特权用户修改它(从而导致本地权限升级)。另一个例子可能是一个Web应用程序,它在同一主机上有一个暴露的匿名FTP服务器,这可能导致源代码和其他敏感文件的泄露。这些问题不是应用程序本身固有的,而是如何在其环境中实现的。
通信分析是了解目标与目标如何与其他进程和系统交换信息。通过监视或主动通过不同入口点发送精心制作的请求,并检查响应是否产生了不安全的状态,就可以找到漏洞。许多Web应用程序漏洞都是通过这样的方式找到的。网络和数据流图(如果有的话)对于全面了解情况非常有帮助。
虽然对这种模式需要了解特定于应用程序的通信协议,但对应用程序内部工作的理解则不然。在这种分析模式下,用户影响的数据如何在系统中传递和转换,或多或少被视为黑盒测试,重点在于监视和发送请求,并分析出现的响应。
如果我们回到我们早些时候假设的金融门户网站,我们就可能会想看看允许客户以不同货币购买预付信用卡的功能。假设一个购买请求接受了以下参数:
· fromAccount:花费资金购买预付卡的账户。
· fromAmount:fromAccount(例如100)账户的货币存入卡片的金额。
· cardType:要购买的卡类型(例如USD,GBP)。
· currencyPair:fromAccount和cardType的货币对(例如CADUSD,CADGBP)。
我们可能要做的第一件事是发送一个标准的请求,以便我们知道一个正常的响应应该看起来像一个基线。从CAD帐户购买$82美元的卡的请求和响应可能如下所示:
我们可能不知道在幕后发生了什么,但是状态属性status的结果是OK。现在,如果我们将fromAmount调整为负值,或将fromAccount调整为别人的账户,那么可能会返回错误的响应,指示正在执行验证。如果我们将currencyPair的值从CADUSD更改为CADJPY,我们将看到toAmount从82.20更改为8863.68,而cardType仍然是USD。通过使用更有利的汇率,我们就能够获得更大的回报,而期望的卡类型保持不变。
如果我们能够访问后端代码,就可以更容易地知道用户输入中发生了什么,并提出更彻底的测试用例,从而可以更精确地触发安全漏洞。也许在客户端上没有暴露的另一个请求参数可能以潜在的恶意方式改变了预期的行为。
代码和二进制分析是为了理解用户影响的输入是如何在目标应用程序中传递和转换的。借用“实用恶意软件分析”中的类比,如果最后三种分析模式可以与尸体解剖过程中的外观进行对比,那么这种模式就是解剖开始的地方。
有多种可以进行静态和动态分析的活动。这里有几个:
· 数据流分析。这对侦察入口点和了解数据如何流向潜在的不安全状态非常有用。当我在通信分析的背景下试图让有效负载工作时,我会以不同的方式调整它以尝试去达到这个虚拟的不安全状态。与这种模式相比,我可以先检查一下这个不安全的状态是否真的存在,如果是的话,找出如何制作我的有效载荷以更精确地到达那里。如前所述,这种模式的好处之一是能够找到不安全的状态,并能够向后工作,为相应的入口点制造有效载荷。
静态和动态分析在这里互相促进。如果你想从A点转到B点,那么静态分析就像是读地图一样,动态分析就像获得交通和天气状况的实况概览。从静态分析中获得的应用程序的广泛而抽象的理解得到了来自动态分析的更加狭隘和具体的理解的补充。
· 导入分析。通过分析导入的API,可以深入了解应用程序的功能以及与操作系统的交互方式,特别是在没有更多上下文的情况下。例如,使用了加密函数可以说明某个资产被加密保护。你可以追踪函数调用以确定它正在保护的内容以及是否正确保护。如果程序正在创建一个进程,你可以查看确定用户输入是否可以影响该进程。了解软件如何与操作系统进行交互可以让你了解可用于与之交互的入口点(例如,网络监听器,可写文件,IOCTL请求)。
· 字符串分析。与分析导入的API一样,字符串可以提供对程序功能的一些了解。我倾向于寻找诸如调试语句,key/token之类的东西,以及任何看起来可疑的东西,它不符合我期望程序的功能。有趣的字符串可以追溯到他们的用法,并查看是否有从入口点可到达的代码路径。区分作为核心程序一部分的字符串和作为静态导入库一部分的字符串是很重要的。
· 安全扫描分类。自动化的源代码扫描工具可能有助于寻找通用的低级漏洞,但在寻找基于上下文或基于设计的漏洞时几乎没有用处。由于存在大量的误报,我通常不会觉得这是最有效的用途,但是如果它产生了很多已确认的漏洞,那么可能说明安全编码实践的实际情况比较糟糕。
· 依赖分析。这涉及到对可利用的已知漏洞的依赖关系(例如,开源组件)进行分类,或者找到在目标应用程序的上下文中可以利用的公开未知的漏洞。现代的大型应用程序通常建立在许多外部依赖项上。它们中的一个子集可能存在漏洞,这些漏洞的一个子集可能会“冒泡”到主应用程序并通过入口点被利用。常见的例子包括Heartbleed,Shellshock和各种Java反序列化漏洞。
· 存储库分析。如果你有权访问代码存储库,则可能有助于确定研究人员通常感兴趣的领域。除了具有比二进制更丰富的上下文以外的好处,这种方式更容易找到旧的代码区域,这些代码在很长一段时间内并没有改变,而这些领域中的代码将桥接分段组的开发工作。
代码和二进制分析通常需要比其他模式要花费更长的时间,并且可以说更加困难,因为研究人员经常需要将应用程序和技术理解为与开发人员几乎相同的程度。在实践中,这些知识通常可以分散在不同的开发团队之间进行分配,而研究人员需要从整体上对其进行有效的理解。
我不能夸大在这方面编程的能力是多么重要。一个能用他们的目标应用技术编程的研究人员几乎总能更好地提供更多的价值。在攻击方面,发现漏洞变得更加直观,并且更容易适应多种环境的漏洞。在防御方面,可以提供非泛型的补救建议,以针对代码级别上的脆弱性的根本原因。
与知识领域相似,将这种分析模式与其他方法结合起来有助于使事情进行的更加快速,并增加发现漏洞的可能性。
其他的思想和经验教训
本节将介绍一些值得一提的其他想法,这些想法在以前的章节中可能不太容易适用。
漏洞复杂性
漏洞的复杂性各不相同。一方面,存在一些微不足道的漏洞,这些漏洞在高度易于审查的领域(例如经典的SQLi身份验证绕过)中使用了直观的漏洞利用代码。在另一方面的结果是预料之外的系统之间的相互作用的元素,通过自己既不安全也不严重的工程,但导致漏洞的时候却是连在一起的(如克里斯DOMAS”记忆天坑”)。我倾向于区分光谱两端的“一阶脆弱性”和“二级脆弱性”,但可能有不同的方法来描述它们。
现代的漏洞已经不是单一的漏洞了。它们往往是一连串的漏洞,加起来就是一个完整的系统入侵。
在团队中工作
向你的团队介绍你所知道的和不知道的事情通常是很有帮助的,这样你就可以在你的专长领域委派任务(理想情况下),同时也有机会在弱领域得到成长。假装和含糊是适得其反的,因为知道得更好的人会很容易地嗅出这种心理。如果诚实才能成为政治,那么也许这不是一个理想的团队合作。另一方面,你不应该指望你所知道的一切都能得到满足。学习如何独立学习可以帮助你变得自立,并帮助你的团队提高工作效率。
在定时项目中,团队的组成可能是发现漏洞数量和质量的决定性因素。根据项目的规模和持续时间,有更多的分析师可能会更快的拿到结果,或导致额外的开销,并产生适得其反的效果。我一直以来最好的项目团队的一个显著特点是,除了良好的关系和沟通之外,我们还有不同的技能,它们相互作用,增强了我们的个人能力。
我们还被委托了可以并行的任务,这些任务已经结合在一起。这里有些例子:
1. 鲍勃搜寻入口点和他们的参数,而爱丽丝寻找易受攻击的sink。
2. 爱丽丝将有效载荷填充到易受攻击的接收器中,而鲍勃将接收器的协议转化为接收器的相应入口点。
3. 鲍勃通过动态分析客户端请求来反转结构,而爱丽丝则通过分析如何静态接收它们来做出贡献。
4. 鲍勃在网络上查找可访问的文件共享,而爱丽丝通过它们查找有价值的信息。
总的来说,在团队中工作可以提高工作效率,但要做到这一点需要一些努力和远见。重要的是知道何时添加成员不会产生生产力,以避免开销。
最后的笔记
感谢你抽出宝贵的时间阅读本文。我希望这在你挖掘安全漏洞时能够解决一些疑惑。进行研究时有挫败感,这是很正常的事情(我不认为会消失)。这是一个不断学习的过程,它超越了可以教你一天的工作或任何单一的资源。我鼓励你自己尝试事物,并学习其他人如何处理这个问题,这样你就可以聚合、组合并将每个元素合并到你自己的方法中。