1 风险评估和威胁建模(Risk Assessment and Threat Modeling)
你写一行代码之前,花时间去设计你的软件与安全意识。正确的做这些是非常困难的;如果你的安全分析过程看起来简单,你可能错过相当根本的东西和失去适当地安全编码设计的大部分好处。
风险评估和威胁建模的三个步骤:
- 评估风险。确定你不得不损失多少。
- 确定潜在的威胁。算出你的代码可能被攻击各种事情(包括你的框架和库代表你做的事情)。
- 减轻威胁。确保您的代码可能被攻击的部分得到很好的保护。
1.1 评估风险(Assessing Risk)
评估你的代码可能造成破坏的风险,你应该首先假定您的程序将被攻击。
1.1.1假设你的软件将受到攻击
攻击者攻击你的程序花费的时间和精力多少将取决于几个因素,包括:
- 程序掌握的数据的价值。它是否存储成千上万的信用卡号码或用户的收藏食谱?
- 为代码提供服务的公司的可信度和安全性。
- 购买程序的特定的客户。是否你的字处理程序被Joe’s Auto Repair或 Big Megacorp,Inc. 使用?
- 你的程序的分配范围。应用程序是被一个单独的小型工作组使用,还是建在一个操作系统上,即将全球发布?
基于这些因素,你需要决定什么级别的风险是可以接受的。数据丢失,贵公司将花费1000美元来纠正不证明一项10000美元的开发工作能关闭所有潜在的安全漏洞。另一方面, 从长远来看,损害公司的声誉可能比设计和开发安全的代码花费是更高的成本。
1.1.2评估风险
评估风险时需要考虑一些因素:
- 如果你的软件被成功的攻击,可能会发生什么糟糕的事情?
会使窃取用户的身份,允许攻击者控制用户的电脑,或者只是让黑客在弹球得到异常高的分数吗?
- 发起攻击的难度有多大?
如果利用漏洞要在用户的计算机上安装一个特洛伊木马,可以利用的竞争条件50次程序启动时才会发生一次,您可能决定风险的水平是可以接受的。如果放入一个脚本被脚本小子(script kiddies)(攻击者运行预先写的攻击脚本)或者是通过僵尸网络(破坏计算机网络)自动传播,风险水平要高得多。 - 目标有多大?
你卖出了一百份应用,还是在默认情况安装在成千上万的电脑吗?
默认情况下易受攻击,还是只有在用户选择一个不寻常的设置选项的时候? - 有多少用户会受到影响?
攻击一个最终用户的机器通常会影响一个或两个人,但是一个拒绝服务攻击服务器上,即使只有一个服务器受到攻击甚至可能影响成千上万的用户。同样,蠕虫一种常见的电子邮件程序传播可能感染成千上万的计算机。 - 如何访问目标?
运行程序需要本地访问,或程序通过网络接受请求吗?为了建立一个连接需要认证吗,或者谁可以向程序发送请求?
1.2 确定潜在的威胁(Determining Potential Threats)
风险评估提供了有可能被攻击一些迹象和攻击可能造成多少伤害。下一步是找出你可能会受到怎样的攻击,包括攻击你所有的利益,不只是攻击你的软件也攻击你的服务器,你的公司,等等。为此,您将创建一个威胁模型来描述放置任何有价值的东西(信息、资金等)的转手。
1.2.1创建一个威胁模型
应用程序,守护进程,或其他软件系统的威胁模型应该是一个高级数据流模型,用图解释每信息进入或离开你的代码或代码之间的主要部分的每一个节点。在高级别上,它应该包括这些方面:
- 应用程序将使用的数据类型。
- 应用程序需要处理不可信数据的场景。
- 应用程序使用的数据传输类型。
- 攻击者能够开发一个补丁程序来取代你的应用的方式。
- 减轻这些漏洞的策略。
这个分析的目的,你应该只考虑理论类的攻击,没有实际的具体的攻击。例如,一个字处理器如果没能妥善处理一个损坏的文件,这样可能会允许攻击者注入代码。这并不重要,你的特定代码是否有具体的错误,使这成为可能。
一些潜在的攻击目标可能包括程序输入或输出,存储数据和程序的操作环境。
- 程序输入。如果攻击者可以导致缓冲区溢出,他们可以运行自己的代码或者妥协或系统用户的数据。
- 程序输出(用户或到另一个软件模块)。攻击者可以获得存储在系统的私人信息,或在模块之间的传递过程中阅读和修改信息(中间人攻击)。
- 数据存储在系统(永久存储在数据库中,或暂时的作为一个全局变量存储)。这些数据可能被偷窃发送给攻击者,被攻击者修改或其他破坏。
- 程序环境。程序的执行环境包括打开的文件描述符,环境变量, Mach端口,首选项文件,等等。
1.2.2考虑威胁的类型
需要考虑以下几种类型的威胁,包括威胁数据、服务可用性和系统的完整性。
数据威胁
攻击者可以修改数据,包括:
- 程序内部使用的数据(如进程间消息)
- 按照程序执行的数据(比程序统计分析的数字或一个程序过滤的音轨)
- 存储在磁盘上程序可以访问的数据…
同样,攻击者可以危害数据和获取访问机密。
攻击者可以通过命令程序直接修改或破解数据,或返回不应该被修改或返回的数据。然而,攻击者还可以通过程序控制计算机间接修改或破解数据。
此外,直接修改常常导致进一步访问,可以允许额外的间接修改。例如,攻击者可能会修改直接程序内部数据,然后使用这些修改后的数据注入任意代码向系统的密码数据库中添加一个新管理员。
服务可用性威胁
攻击旨在减少服务可用性称为拒绝服务攻击(denial of service attack)。这些攻击可能导致应用程序或守护进程停止运行,或做一个服务器很忙,合法用户不能访问它。
攻击者可以在许多方面执行拒绝服务攻击:
- 攻击网络堆栈漏洞
- 打开守护进程的连接,开始发送请求,然后非常、非常缓慢继续发送
- 说服让成千上万的人主动攻击你的服务器
- 从僵尸网络向守护进程开放的数以百万计的连接。
当一个拒绝服务攻击是由大量的机器实施的,它被称为分布式拒绝服务攻击(distributed denial of service attack),或DDoS。
系统完整性攻击
攻击系统完整性建立其他攻击修改系统以这样一种方式,它可以不再被信任。如果攻击者可以在代码中找到一个安全漏洞,攻击者可能会:
- 执行恶意代码,尤其是管理员或根访问。例如攻击者可能会导致您的代码执行攻击者的代码利用缓冲区溢出或通过代码嵌入一个URL命令。
如果你的代码是一个使用管理权限运行的守护进程,攻击者的代码也会享受特权。一旦攻击者管理控制电脑,任何减轻威胁的努力都会是徒劳的。 - *模拟一个用户或服务器。8攻击者可能会猜测或得到一个有效的用户名和密码,因此验证为授权用户。
同样,欺骗服务器可以说服客户端应用程序认为它是一个合法的服务器,然后让客户端给提供数据或者机密信息,如密码。
最后,一个欺骗服务器可以说服一个天真的用户服务器是合法的。例如,用户可能不会充分检查一个包含web页面窗口来注意到锁图标(或其他指标的一个安全的网站)不见了。使用这样的恶意网站获取用户数据被称为网络钓鱼。 - 否定一个动作。恶意用户可能通过这样一种方式来修改软件以允许他或她拒绝执行一个操作(如使用特定的信用卡号码)。有很多技术可以用来确保认可,如代码签名验证、数据完整性检查,等等。
1.3 减轻威胁(Mitigating Threats)
在你确认你的软件生态系统(应用程序、服务器、当地的守护进程和代理等等) 哪些部分可能会被攻击之后,你必须采取措施来减轻这些威胁,减少他们的破坏性。
1.3.1使用常用的缓解技术
缓解威胁的手段在计算机软件是多种多样的,但是一些核心技术是很常见的:
- 在处理可能来自不可信来源数据时采取额外关注。特别是,安全软件必须验证其输入。
- 利用沙盒,开发人员定义限制你的应用程序,最小化应用程序如果被破坏导致的损失。
- 通过划分应用程序并确保每个部分的应用程序只能访问它所需要的信息来使信息泄露风险最小化。
- 进行模糊测试,向应用程序或守护进程发送坏数据查看是否中断, 修复在这个过程中发生的任何bug。
- 利用内置的安全功能的操作系统,而不是重新发明轮子。
1.3.2 知道取舍
在决定如何减轻威胁时,请记住,经常有安全性和便利性之间权衡。软件安全必须安全性和可用性之间取得平衡。考虑软件设计的两个极端的例子:
- 一个项目需要身份验证在执行任何操作之前使用多个身份验证方法,只有运行足够长的时间来执行该操作,不分享与任何其他程序使用的CPU,然后退出,需要重新授权操作。
这种操作方式非常安全,可能适合一个程序,发射核弹,但很少有人会想要用这种方式来使用文字处理器。 - 另一个程序总是使用root特权运行并且不需要授权可以执行任何操作。
这样的程序易于使用,在物理上安全的计算机没有连接到一个网络,它甚至可能是比较安全的。然而,在大多数正常情况下,这将是一个巨大的安全风险。
显然这两个极端条件没有达到理想的安全性和便利性之间的平衡。作为一名开发人员,这是你的责任来决定您的软件哪些地方应该融入基于当您的程序被破坏(风险)会造成的连续损害,以及软件可能面临的攻击类型(威胁)。
1.4 完成之后(After You Finish)
即使当你完成这个评估,你的工作没有完成,你应该重复这个定期评估。特别是:
- 每当你做任何设计决策,考虑如何设计决策改变你的威胁模型,并相应地更新您的模型。
- 当您添加新特性或功能,为这些新组件创建威胁模型。
- 编写代码时,请注意威胁模型并确保代码遵循其指导。
除了避免错误的设计,还必须采取措施确保您的代码健壮性来在实现中对抗攻击漏洞。关于如何做到这一点,在下一章你会了解更多。
1.5通用标准(Common Criteria)
美国政府、加拿大、英国、法国、德国和荷兰合作开发一套标准化的流程和标准,可用于评估软件产品的安全性。这个过程和这套标准被称为通用标准(Common Criteria)。
作为一个尝试系统化安全评估,通用标准可以帮助显示大量的你可以寻找的潜在问题。另一方面,对于任何标准化方案,通用标准不能预见的漏洞还没有见过的。因此,通用标准标准比人们希望的不太灵活。