前言

软件安全一直被视为一项神秘而又高级的领域,其中的软件安全开发和安全测试更是很多普通的开发者和测试人员难以企及的工作。但是对于常规的安全开发和安全测试,普通的开发人员和测试人员是可以担任的。而且通过这些常规的安全开发和安全测试,可以预防绝大部分中低级安全漏洞。

为什么要做威胁建模

软件的安全漏洞主要来自业务需求,业务流程,软件架构,代码开发和第三方依赖包等,并不是仅仅来自某一个单一方面。并且由于某一类角色基本上很难对于业务需求,软件架构,代码细节以及各种基础设施等都很熟悉,因此对于软件系统的全方位的安全漏洞,如果仅仅希望由某几个安全测试人员通过安全测试去发现是非常困难的。所以需要有一种体系和实践来帮助团队全方位地识别和发现安全漏洞,并且最好是能在代码开发之前发现业务流程和架构设计上的安全威胁,以及可能出现的安全漏洞,让开发人员能提前知道并在开发过程中避免产生这样的安全漏洞,从而实现预防安全漏洞而不是报告缺陷。为了解决上面的问题,威胁建模就被设计出来了。下面总结了一些为什么要做威胁建模的原因:

  • 通过威胁建模可以让团队更好地理解系统的安全现状以及安全目标
  • 可以预防一些安全漏洞进入产品并被人利用
  • 可以帮助团队制定安全漏洞发生后的应急计划
  • 可以集中化定制安全相关的工作计划
  • 可以在软件开发生命周期中前移安全工作,从而缩短安全问题的反馈周期,并进一步实现每一个人都对安全负责的理念
  • 仍然有不少安全漏洞或者安全威胁是不能靠自动发现
  • 提供给团队一个公开的,高效的环境来专门做安全相关的工作
  • 可以驱动出在软件开发生命周期中的一些其他安全实践:比如安全自动化扫描,安全测试,安全编码等。

什么是威胁建模

威胁建模是一种实践流程,在其中需要使用安全攻击者的思维去思考如何攻击被测系统,并通过这种思维去发现系统中的威胁,并最终减少它们。在实践流程中,实施威胁建模就是在软件开发团队中举行的一个工作坊,并由主持人引导队员进行一些列活动。最终的产出物就是团队的故事墙上的一系列安全故事卡,当完成这些安全故事卡之后,系统的安全威胁就会减少。

威胁建模中的基础定义与准则

在软件安全领域有非常多的基础定义和准则,如果需要全部了解并掌握是需要很多时间的。所以要求一个没有做过专业安全工作的普通程序员,业务分析师,测试分析师等去了解并掌握它们也是很不现实的。为了让团队成员能真正有效地参与到威胁建模中,他们需要了解并同意一些基础定义与准则。而这些基础定义和准则可以帮助团队中的每一个人达成共识,在威胁建模工作坊开始前,不同团队在根据自身安全成熟度的情况下,基于这些基础定义和准则一定要先达成这个共识,从而方便工作坊的进行。

  • 资产(Asset),资产指团队需要保护的东西,比如一个操作系统,一个数据库,一个密码等
  • 漏洞(Vulnerability),漏洞主要是指团队所要保护的资产中的缺陷,这些缺陷可以被乱用或者误用来攻击资产。而团队需要修复这些漏洞或者减轻漏洞所带来的危害。
  • 威胁(Threat),威胁指会破坏需要保护的资产的东西,比如一个攻击者,一个病毒程序等。
  • 风险(Risk),一个风险是指一个潜在的可以使用漏洞来攻击资产的威胁,并且可以用来评估资产可能受到的危险程度。攻击向量(Attack Vector)攻击向量是指一个攻击者执行攻击的方法,比如发送一封电子邮件或者发送一个HTTP POST等。
  • STRIDE,STRIDE是当前最主要的几种攻击类型的组合名称,它们分别是:仿冒(Spoofing),篡改(Tampering), 抵赖(Repudiation),信息泄漏(Information Disclosure) ,拒绝服务(Denial of Service),提升权限( Elevation of Privilege)这六种类型。每种类型在实践中又有许多具体不同的实现,比如:
威胁具体的攻击实践相应的安全领域
欺骗(Spoofing)欺骗系统的认证系统可以让攻击者可以做一些他不被允许做的事情。比如通过CSRF获取他人身份并冒充他人进行攻击。认证(Identity); 鉴权(Authorization)
篡改(Tampering)破坏信任机制并修改系统运行的代码或者数据。比如通过中间人攻击串改用户和服务器之间的数据完整性(Integrity); 有效性(Validation); 注入(Injection)
抵赖(Repudiation不可抵赖性可以让系统的使用人员对自己的操作负责,不能否认自己的操作。比如有一个人删除了数据库中的数据,如果有相应的操作和审计安全日志,他则无法否认自己的操作不可抵赖性(Non-Repudiation);日志(Logging); 审计(Audit)
信息泄漏(Information Disclosure)信息泄漏主要是指信息被没有授权的人截取了或者信息没有被保护起来并公开出来。比如通过模糊测试,发现服务在特定请求下返回的错误信息里面包含有技术栈的详细信息机密性(Confidentiality); 加密性(Encryption)
拒绝服务(Denial of Service)拒绝服务攻击主要是通过过量请求,或者屏蔽服务,或者破话服务系统来让服务不可用。比如使用SYN攻击,通过发送大量的半连接请求,耗费服务器的处理器和内存资源,从而是服务器拒绝其它正常请求。可用性(Availability)
提升权限(Elevation of Privilege)提升权限主要是指攻击者通过系统权限和认证系统的漏洞或者缺陷来获得系统更多的访问权限。比如通过系统的命令注入攻击而获得管理员权限授权(Authorisation); 隔离(Isolation)

更多细节请参考:https://en.wikipedia.org/wiki/STRIDE_(security))

img

什么时候做威胁建模

一般情况下在瀑布模型里面威胁建模都是在业务分析,业务架构,技术架构等工作完成之后和开发之前进行的。但是在敏捷开发团队里面,威胁建模一般都不会只做一次,除了项目最开始那次以外,在重要的功能开始之前也一定会做,也可以在整个软件开发流程中有需要的时候就要做,所以是持续的迭代进行的。

怎么做威胁建模在威胁

建模实践流程中,为了尽可能的适应不同团队的情况,总结出了四个主要的阶段,它们分别是:

  1. 审查数据流和架构图
  2. 确认可以被攻击的资源与可能的攻击者肖像
  3. 生成攻击树
  4. 确定如何消除或者减少风险

审查数据流和架构图

在威胁建模开始前需要准备好系统的一个数据流图和一个架构图,这样在威胁建模中整个团队可以一起统一基于这两个图来做分析和讨论,然后一起确认信任边界(trust boundaries)并找出可能存在问题和风险的地方。这个是整个威胁建模中最为重要的一步,因为详细的正确的数据流图和架构图可以帮助参与人员尽可能正确和没有遗漏的了解整体系统,并且尽可能澄清自己有问题的部分,或者针对有问题部分深入讨论,甚至有可能就在这步发现一些威胁或者漏洞。然后记录下在这个步发现的所有疑问,威胁或者漏洞等。下面是一些在这步经常可能会问到的一些通用问题:

  • 这里的鉴权是怎么做的?
  • 这里有什么代理服务嘛?
  • 密钥是怎么样进行分享的?
  • 它们有不同的访问权限和等级嘛?
  • 这个系统有多少个级别?
  • 为什么?

可以通过一些的专业的软件来画这个流水线图和架构图,也可以通过一个大的白板来画。以我们的经验来讲,在威胁建模的工作坊中使用白版的效率更高,因为你可以随时快速添加,删除或者修改,快速记录提出的疑问和回答等,最后可以通过照相的方式保存下来。当然,如果你真的讨论物理白板子,下面这些专业的威胁建模工具可以很好的帮你完成流水线图等。

确认可以被攻击的资源与可能的攻击者肖像

在团队审核和讨论数据流图和架构图之后,团队需要他们列出系统中最有价值的资产,从而定义出那些是我们最需要保护的资产。这些资产不仅仅是系统所存储的数据,而且还包括源代码,密钥,甚至计算能力等。对于要保护的资产,我们需要思考是谁要侵害我们的资产。其次明确和描述出攻击者的肖像是非常有帮助的,特别是那些对于安全和攻击没有什么经验的团队。下面是一些攻击者的例子:

  • 内部人员- 前员工
  • GDPR 审计员
  • 竞争者
  • 第三方合作者
  • 低技能攻击者(脚本小子)

然后团队需要将攻击者和攻击者感兴趣的资产映射起来。虽然这些映射看起来可能有一点杂乱,但是在我们的实践中已经证明了它们对于下一步生产攻击树却是十分重要的。 在实践中,我们还会把资产用灰色表示,而供给者用红色表示等。通过良好的可视化的方式可以让大家对于资产和攻击者等的印象更加深刻,帮助其思考。

生成攻击树

攻击树是用来列举攻击者为了完成其攻击目标可能使用的不同方法。首先将攻击目标作为攻击树的根节点,然后对于每一个字节点上的攻击方法回答一个问题:“他们(攻击者)怎么做到它?”但是怎么从映射攻击者肖像到创建攻击树啦?可以创建一个小型的头脑风暴开始。首先要求参与威胁建模的每一个人花几分钟时间回到下面这个问题,并各自得到一条或者多条答案: 攻击者(谁)对于什么系统(资产)可以通过什么手段(攻击)得到什么(收益)? 然后再对于这些一答案进行清理和讨论,最终选出几条大家认为最为重要的威胁。这几个重要的威胁就是攻击者的目标,我们就可以将其作为攻击树的根节点们。在实践中我们发现,需要创建多少个攻击树不仅仅是取决于威胁的重要性,还取决于参会人数。人越少,攻击树的树木就应该越少,比如3-5个人的情况下一般工作于1棵攻击树上的效率比较高。因为人太多了会过于发散,然后导致效率降低,并且偏离正确方向。当然这个也不是绝对的,3-5个人也只是我们的一个经验值,应该满足大部分团队的情况。

确定如何消除或者减少风险

通过上面的这些步骤,团队也许会得到一个令人感到畏缩的可能的风险列表。如果考虑一次性修复它们是不切实际的,所以团队需要根据自身的资源,技术能力以及威胁对于业务的影响等确认初3个或者4个最高优先级的风险。让业务分析师和利益相关者深入的参与到风险的优先级确认工作中是十分关键,因为他们理解并能给出这些风险在整体上对于业务的影响。一旦完成了以上这些工作,我们就可以聚焦这些高优先级的风险上,然后针对这些风险制定出相应的解决或者改善方案,并在故事卡墙上创建出相应的故事卡。 img

突发事件

在威胁建模工作坊上可能出现各种突发事件,所以工作坊的主持人需要足够的经验,并且能灵活处理这些突发事件。比如有人问了一个问题,但是没有任何人回答;如果团队给了一个不完成的的或者不正确的数据流图等。我们经历过这些情况,需要主持人随机应变,比如对于没有人回答问题,主持人可以换一个问题问,或者指定某人回答(前提是主持人需要了解参与人员每个人的角色和职位),然后保证流程能正常进行。

做威胁建模时的困惑

对于威胁建模不是很熟悉的人在做威胁建模时总会遇到这样那样的问题,除了问题还会遇到不少困惑。其中经常遇到的一个最主要的困惑就是:感觉威胁建模永远做不完。在敏捷开发中,然后事情都是根据优先级然后持续迭代进行的。所以威胁建模也是根据架构和业务功能持续迭代进行的,只要业务不做完,威胁建模就会持续迭代做下去。其次在单次威胁建模也是有优先级的,只关注优先级高的严重的威胁,所以对于单次威胁建模来讲,只要有明确的DOD(Definition Of Done),然后是能做完的。

总结

当威胁建模完成之后,在代办卡墙上一般都会多不少安全威胁相关的故事卡,并且这些故事卡正式减少安全漏洞的关键。其次通过完成这些安全故事卡,开发团队的安全意识和技能都能得到很好的锻炼,从而提升整个团队的安全成熟度。但是如果这些安全故事卡只是静静的呆在代办故事卡墙上,再也没有人去谈论它们,完成它们,那么之前做的威胁建模也不能算成功。在团队里面,必须需要一个人来专门管理并跟进这些安全故事卡,比如IM或者QA。或者制定一些定期的讨论来帮助团队持续关注和跟进它们。 而对于威胁建模实践流程,还有一下一些注意事项:

  • 你不需要成为专业的安全工程师或者安全专家才能去做威胁建模
  • 你可以发现一些通过任何自动化都无法发现的安全威胁
  • 你可以在敏捷开发生命周期的任何阶段做威胁建模
  • 通过询问“怎样可以产生错误”来扩展当前的工作方式和方法
  • 也许有很多方法可以发现安全威胁,但是通过对STRIDE进行头脑风暴的形式是一种快速并灵活的方式
  • 产出物可以是故事,任务,验收条件等具体的
  • 在许多安全社区里面都有着大量的关于威胁建模的资料

附录1, 威胁建模在敏捷和瀑布的比较:

img

标签: none