随着安全得到越来越多的关注,一些跟安全相关的理论(比如 BSI )脱颖而出,但是这些理论虽然提出来已经有一段时间,却很少看到其在开发团队成功地应用。我们知道微软曾在十多年前就提出了 SDL ,却没能在业界推广开来,并不是人们不认可微软这种从软件生命周期保障安全的理念,而是出于其落地实施的难度让很多企业知难而退,那么这些安全理论对我们的软件安全真的有帮助吗?安全实践能落地吗?
很幸运地我有机会在一个成熟的敏捷开发交付小组中经历了从完全没有安全实践到 BSI 的过程,我们也曾遇到过很多困难,但最终得到了客户的认可,并成功把安全实践推广到了整个团队,所以想跟大家分享一下我们是如何将安全在敏捷团队落地的,希望能给大家一些帮助。文中会拿 Web 系统举例,但一些落地的实践同样适用于非 Web 系统。
为什么安全理论很难落地?
结合对一些团队的了解,原因大多数来自以下三个方面:
-
认为安全不重要
-
认为安全太难,需要很广很深的领域知识,只有专业人员才能做到
-
不知道应该用什么样的流程来做安全
那么针对第一点,因为我本身也是交付团队的一员,我观察到的大多数的软件开发团队,不管是业务分析师,开发人员,测试人员,体验设计师还是项目经理,都很少有人真正把安全作为非常重要的一件事情,尤其是在交付压力比较大的情况下,我们都会舍弃对于安全的投入,而花时间在更容易可视化出来的用户功能上。安全,很多时候就像灭火器,如果不发生火灾,我们甚至都感觉不到它的存在。那么,安全,真的重要吗?
换位思考一下,如果我们是用户,摆在我们面前的有两个系统,系统 A:设计非常完美,功能缺陷几乎没有,性能也很棒,但是没有做任何跟安全相关的防护,用户的敏感信息很容易泄露;系统 B:设计比较差,有一些功能缺陷,性能也差一点点,但是采取了特别多的安全措施,能够保障用户的数据安全性;我们会选择哪一种?
相信几乎所有人都会毫不犹豫选择 B 系统,除非这是一个完全没有用户敏感数据完全不需要安全保障的系统(那这样的系统又有什么用?),所以只要我们把自己放在产品使用者的角度,而不是产品制造者的角度,就能很容易地理解和认可安全对于软件系统来说是比功能更重要的一个因素,是软件的灵魂。
那么对于很多已经深刻认识到安全重要性的团队,为什么依然很难将安全理论落地呢?原因大多来自前面提到的第二点和第三点,一是从技术上认为安全是一个很难的领域,需要专业的安全人士;二是从流程上不知道该如何开展;鉴于这两个原因都可能导致安全需要巨大的投入,所以很多团队望而却步。那么安全真的这么难落地吗? 接下来我会简单介绍一些 Web 安全知识,然后通过我所在团队的落地过程给大家一个答案。
如何让安全在敏捷团队落地
什么是 Web 安全?
所谓 Web 安全问题,就是攻击者可以通过非正常的手段,获得 Web 系统访问权限,从而破坏网站行为,盗取甚至修改用户数据的一系列问题。
那么为什么攻击者可以获得 Web 系统权限呢?这种几率到底有多大呢?如果可能性非常小,我们是不是可以不花费太多精力在安全上面呢?
我们来看一下 Web 系统的组成,一个最简单的系统都至少有这么几个部分:
如上图,浏览器发送请求到服务器,服务器给浏览器响应,服务器会查询数据库,数据库返回结果。在这个过程中,我们开发的 Web 程序不可避免的存在安全漏洞,甚至我们开发系统所使用的编程语言也会有安全问题,在开发过程中,很多时候我们会引用一些第三方的工具、组件,而第三方的安全性也没有办法保障,甚至数据传输过程中使用的协议,操作系统本身也会有安全问题。所以可以想象一下,如果我们不做任何的安全防范,那么每一个软件都是一个非常脆弱的系统,很容易出现安全问题。
常见的 Web 安全问题
既然这么多环节都有潜在的安全风险,那么该如何着手呢?可以参考 OWASP TOP 10 对最严重的 Web 应用程序安全问题有个大致的了解。
敏捷开发模式现状
我们是一个已经实施敏捷开发七年的团队,一共有五十多人,划分成不同的 Feature 小组进行日常的工作,其敏捷开发模式已经非常成熟,我所在的 Feature 小组有 6 个开发人员,1 个业务分析师,1 个 QA,我们每个小组的交付模式都是这样的:
如上图,以用户故事为单元,所有的用户故事都会经历一个从分析到最后给客户演示的生命周期,多个用户故事组成一个 Feature,然后我们会进行 Feature 的功能测试,给客户展示整个功能,最后在发布之前,客户会邀请第三方的专业安全公司做渗透测试,然后找我们的开发团队修复安全缺陷。
那么这种方式有什么问题呢?
-
守门员模式,安全测试非常滞后
-
安全问题的修复时间非常有限
-
只有少数人关注和了解安全
-
依赖独立的渗透测试
所谓守门员模式,指的就是把所有的问题和风险都留在最后,靠少数人来保障,在当时的开发模式下第三方的安全公司就是我们系统的安全守门员,可想而知,如果我们的团队对安全没有任何了解,在用户故事的开发阶段引入的安全问题要等到发布之前才能够被发现,安全测试是非常滞后的,反馈周期特别长。
另外当第三方的安全公司发现问题后,留给我们团队修复问题的时间特别有限,因为渗透测试是发布前的最后一个阶段,长时间的修复又会导致发布延期,所以经常会导致安全修复以补丁的方式发布。
而且除了少数修复过安全缺陷的开发人员对安全有一点点了解之外,团队内是没有人关心安全的。
最大的问题是,所有的安全防范都依赖最后的独立的渗透测试。虽然因为执行渗透测试的是专业的第三方安全公司,他们有专业的安全知识,可以发现很多公共的安全问题,也可以提供专业的极具权威性的安全报告,但这种方式的渗透测试有个致命的弱点,他们对业务知识了解不够,很难发现跟业务相关的安全问题,而这一类的安全问题又占了相当大的比重。
可以看到,这种敏捷开发模式的现状就是:试图将安全注入一个已经成型的系统中。
安全落地尝试
那么了解了之前开发模式存在的问题,安全又这么重要,客户和团队都希望可以改变这种现状,提高安全质量,减少补丁,让每一个人都关心安全,但是我们都担心安全需要巨大的投入影响功能的发布,所以我们决定选择一个 Feature 小组做为安全试点,目标周期为一个月(我们的发布周期),观察投入产出比,然后决定是否要在整个团队实行。
首先我们小组开始学习BSI,我们认为它所传递的是这样一些理念:
-
将安全融入整个软件开发过程中
-
所有团队成员一起为安全负责
-
安全的设计和实施一个持续进行的过程
那么在一个几乎没有安全知识储备的团队中,如何将以上理念在团队应用呢?我们遇到了很多的困难,比如:
-
不知道怎么把安全和日常开发结合起来
-
不知道如何编写安全需求,怎么做安全测试
-
接受了很多安全培训,不知道如何下手
-
对安全缺乏专业的认知, 对安全开发和测试没有信心
-
不知道如何满足客户期望
分析这些困难,我们开始迈出了艰难的第一步。
首先,召集团队的核心成员(包括了业务分析师,开发人员,测试人员,技术主管),同时我们邀请了公司的一位安全专家帮我们解答难题,大家头脑风暴,参考OWASP TOP 10, 结合曾经项目上出现过的安全问题以及对于业务领域的深入了解,尝试总结属于我们自己的安全问题项目并且和OWASP TOP 10 进行关联,比如我们讨论后的成果是这样的:
可以看到,我们总结出来的这十项并不是将OWASP TOP 10 调换顺序这么简单,我们是针对业务需求,有针对性地进行了重新整理和组织,比如其中的 Sensitive Data Exposure ,我们就结合项目将它划分成了四类(1.Authentication,2.Error Handling,3.Code Leak,4.Cookie Management),之所以会划分的这么具体,是因为我们自己的 TOP10 更贴近实现。另外我们还针对每一项添加了项目上的例子作为参考,让团队每一个人都清楚地知道我们自己的 TOP 10 都是什么样的业务场景下可能出现的安全问题。
然后我们将项目专属 TOP 10 作为模板加入到了每个用户故事中,这么做有两个好处,第一,业务分析师在写用户故事的时候,可以将其作为参考来编写安全验收标准;第二,如果业务分析师在缺乏安全知识的情况下很难编写安全需求,我们可以将其直接作为安全需求以防遗漏。
当然这还远远不够,更理想的情况是在需求分析阶段,业务分析师和客户在讨论需求的过程中尽量参考一些基本的原则,比如最小权限原则,来确定和编写更加准确的安全验收标准。如下图。还可以让更多的人参与到需求分析阶段,通过威胁建模等手段分析出更全面的安全需求。当然这就需要我们的业务分析师增加安全相关的知识储备,我们也在向这个方向努力。
然后在用户故事的启动阶段,业务分析师,QA 和开发人员会一起针对用户故事模板中我们自己的TOP 10 进行筛选,将和用户故事相关的内容标识出来作为安全验收标准。如果在故事分析阶段,业务分析师已经遵循一些原则细化了安全验收标准,在这个阶段,也可以多个角色针对这些安全验收标准进行探讨,确保大家理解一致。
到了用户故事的开发阶段,通常开发人员都会按照验收标准来编写代码和测试,基于我们已经有了足够的安全验收标准,相应地,开发人员也会编码来实现这些安全条件并且添加相应的自动化测试保障,当然,除了满足安全验收标准之外,我们也会做一些静态代码的扫描和第三方依赖的扫描,双重保障。
用户故事的验收阶段非常重要,因为如果在这个阶段发现缺陷可以快速修复,我们一般是QA,开发人员和业务分析师一起,逐个验收我们之前制定的安全验收标准。当然,除了简单地从前端进行验证,针对安全验收我们需要借助一些工具(如 Burp Suite ),绕过前端修改请求,检查是否后端接口也作了相应的防范,如果发现安全问题,会在这个阶段及时修复并且增加相关的测试保障。
到了用户故事的测试阶段,QA 会做跟安全相关的探索性测试,在这个阶段,需要 QA 从一个全新的视角来做测试,之前我们的模式是从正常用户的角度来测试功能,而针对安全的探索性测试则截然不同,我们要用攻击者的角度来思考问题,尝试各种看似不可能的手段,寻找安全漏洞。另外,在这个阶段,我们也会借助一些自动扫描工具(比如 ZAP ),来检测是否有一些通用的安全问题。
安全的演示阶段比较有挑战性,前面提到过,它不像功能需求那么可见,所以我们采用了一种全新的方式去展示,通常功能演示我们是给客户展示用户界面,如何使用系统等,而对于安全,我们尝试了展示安全缺陷以及我们的缺陷分布分析。比如在这一个月里,我们发现了六个安全问题,其中两个是通过 ZAP 扫描出来的共通的安全问题,另外四个是和业务强相关的安全问题(比如账户 A 可以通过特殊手段修改其本来没有权限的数据,属于我们自己的 TOP 10 的 Authentication 那一类)。
回顾整个过程,其实我们在用户故事的每个阶段都增加了和安全相关的实践,并且让团队所有人员都参与了进去,将安全融入到日常的工作中,不断改进,持续关注,而这些正是 BSI 所传达的理念。
客户看到我们的安全成果展示后非常满意,进而在我们整个团队开展了这样的安全实践。
在维持这样的安全模式几个发布周期之后,我惊喜地发现我们的开发人员开始有了安全的意识,比如前不久我们有一个用户故事需要实现一个邮件模板,系统要求能够接受用户定制化的 html,功能实现非常简单,可是开发人员一筹莫展,接到用户故事后马上找到我,探讨如何让我们的系统允许接受 html 后还可以避免 script 攻击,这让我深刻感受到,BSI(Build Security in our DNA)这个理念的精确含义,我们不是为了让大家遵循实践而去实践,而是让每个人都有安全的意识,当我们每次接触一个新的功能,马上会想到可能有哪些安全问题,而不是急于实现功能,长此以往,安全就真的进入了团队的 DNA。
总结
回想之前我们想要开始在团队实施安全时候的恐惧,止步不前,到最后我们成功将安全实践落地并且推广,这个过程让我体会到,从一个小组开始尝试,观察投入产出比,再推广到整个大的团队是个很好的实践。另外,不要期望一步到位,迅速成为安全专家,安全的设计和实施是一个持续进行的过程,可以从日常工作中的点滴做起,从保障每一个安全需求做起,想象一下,如果我们每一个用户故事都注入了和安全相关的实践,那么 feature 就会是这些安全的用户故事的结合,系统就会变成一个充满安全投入的整体。
和之前的靠最后的渗透测试来补救安全问题的方式相比,这种从源头就将安全渗透进软件系统的方式更能保障我们软件的安全。
作者介绍:
刘建华,ThoughtWorks 咨询师,在测试行业将近 10 年,对测试理论和方法有深入的理解,擅长敏捷软件开发模式下的质量保障,引导和参与了敏捷团队安全实践从无到有的过程。
给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ , @丁晓昀),微信(微信号: InfoQChina )关注我们。
评论