Shift Left在开发安全中的应用

2021-06-17 18:15:48 浏览数 (2)

01

前言

开发安全是一个老生常谈的话题,随着云计算、虚拟化等技术的发展,开发安全在SDL(Software Development Life Cycle)、DevOps中的体现也倍受关注。很高兴受邀参加EISS开发安全分会场的邀请,谈谈自己对开发安全的一些理解与思考。会上分享的材料也都提供给主办方,并且也在SDL专属群中分享。考虑到PPT终究只是个框架,很难描绘出会议上分享的内容,故趁着假期挑灯夜战记录下来。

02

从测试视角看左移

提到开发安全,我们肯定会想到“左移“。但是今天我们尝试从另一个角度来看 - - 软件测试工程。因为安全测试像极了功能测试,都是评估软件质量的方法。在被外界关注的顺序上,功能测试也应该早于安全测试。但软件工程测试种类繁多,为了避免产生歧义,后续文中狭义的称功能测试为软件测试,软件测试不包括安全测试。

2.1 Where Shift-Left?

首先来看“左移“,最早也是出现在软件测试中,这里不谈古老的”V”模型,就聊软件测试工程大牛Arthur Hicken提出的:The Shift-Left Approach to Software Testing。

Arthur Hicken提出:测试左移,指测试活动尽早的介入到软件研发过程中,更多的则强调开发工程师验证自己编写的代码(即:开发自测,包括代码逻辑、接口测试等,从效能方面来看也更加合适)。后来在Gartner的大会上也提出安全左移的概念。

2.2 Why Shift-Left?

其次是为什么要进行左移?答案相比人尽皆知,但是此处为了说明情况或为涉及该领域的同行提供一些素材,引入另一位大牛Capers Jones,Applied Software Measurement : Global Analysis of Productivity and Quality书中的一些图片。(图中数据未做考量与深入研究,仅供说明投入悬殊较大的问题)

图中横轴表示软件研发的主要阶段,纵轴表示软件缺陷的百分比,蓝色线表示发现软件缺陷数的趋势。不难看出在coding阶段发现的缺陷是最多的,占比高达85%。

相比上一张图,此处多了一条橙色曲线,表示发现缺陷的趋势。在测试阶段(尤其是功能测试和系统测试)发现的缺陷占比最多。

较上一张图,又多了一条红色曲线,表示修复缺陷所付出的花销。在研发阶段越靠后,修复缺陷的花销就越大,并且比例类似指数曲线,在coding阶段的1倍,在release阶段直接变成了640倍。尽管不可能在发布前将所有软件缺陷发现并修复完,但是越早发现、越早修复肯定是花销越少的。

类似于软件测试,安全测试中漏洞的发现与修复成本,完全符合这个规律。

2.3 What Shift-Left?

在谈安全左移之前,先看看大多数安全测试的现状。如下图所示,在软件的发布前进行安全测试,通过即发布,不通过则与业务线死磕,在业务大于安全的压迫下,很可能“带病”上线。

传统瀑布型的开发模式还好,在敏捷开发或者DevOps下,安全与开发的矛盾点会被放得更大。所以类似于软件测试,安全测试也应该前置,在产品研发流程中,在靠前的环节嵌入相应的安全活动。

于是,就出现了SSDL、DevSecOps等流程或体系。结合公司的业务场景(硬件安全产品为主)和产品管理体系IPD,将安全活动进行裁剪、改变、融合也构建了适合我们的“基于业务场景的开发安全全景图”。

这种类似的图,想必都已经见过了很多。这并不是说当前已经具备的水平,而是期望发展的目标,将其中任意一项安全活动做得精细化都比较困难。但是开发安全是否就是应该建立庞大的工程体系,否则就做不好了呢?

03

开发安全左移实践

其实不然,我经常在思考如何做好开发安全?不一定是要先建立完善的大工程,才能将开发安全问题收敛。比如针对典型问题进行专项突破,对多个专项进行联动织网,紧盯目标、结合现实做一些力所能及的安全活动,也能解决大多数的开发安全问题。今天主要分享7个小实践案例,进行抛砖引玉。

3.1 源头管控(跳出研发流程)

刚才介绍的基本都是研发流程相关的安全活动,但是仅关注需要进行研发的项目就足够了吗?答案显然否定的,比如外购的软件或外购软件二开等情况,很可能就是不会走研发流程,这些软件的安全性在企业安全中却是不可或缺的一环。

对源头进行管控,应该包括自研产品、外购软件。针对外购软件可以从两个层面进行要求:

  • 安全清单:要求供应商提供能够证明交付软件的安全性报告,以及系统架构、组件清单和版本信息。安全性报告包括但不仅限于代码审计报告、渗透测试报告、漏洞扫描报告等,报告可以由安全公司、供应商自有安全团队出具,具体可根据采购的软件或项目大小而定。对接公司采购部,在供应商第一轮交流中就加入,提出安全要求作为供应商入围必备材料,并力争在技术评分中占据一席之地。
  • 安全响应:除了常规的发现漏洞时,需要应急SLA要求,还要求供应商及时主动同步漏洞信息。这些内容都应该写入到合同中并明确处罚方式,才能保证有效的落地。

3.2 开源治理(进入研发流程)

再回到研发流程中,供应链攻击在最近几年已成为热点,软件中使用第三方开源组件的安全性也倍受关注。一提到开源组件,首先想到的是组件的漏洞,但组件的安全性还包括使用开源协议的合规安全、组件供应链安全、片段代码引用安全等问题。相应的需要有工具进行检测,其一是在内部将工具与Git仓库对接,通过githook触发进行源代码层面的组件安全扫描;其二是对接制品库,从二进制方面进行安全检测。(为了避嫌推荐产品,此处不详细说明使用的工具,有需求的可以留言交流)

在不少的实践中,会经常提到建立内部组件库并持续维护,严格把控入库和开发仅使用内部库中的组件。但这带来的工作量可能不是一般企业能够承担的,所以另辟蹊径选择有效、成本相对较低的方式较为妥当。

开源组件的安全问题较多,最为被广泛讨论的还是组件漏洞。使用工具扫描发现的漏洞数量庞大,以至于不知如何下手修复,怎么办?为了解决这个问题,可以从以下两个角度进行分析:

  • 合规视角:若有客户对组件漏洞风险提要求,那是最直接有效推动修复的方式;其次是结合组件-漏洞的关系,针对非常多漏洞的组件,建议建立黑名单机制。(何为非常多漏洞?具体需要结合实际的使用情况来定,比如知名的fastjson,又如扫出的组件漏洞中,占比非常大的某个组件等等)
  • 攻击视角:能够被利用且危害较大的组件,需要修复。这句话有两层意思,一是能够被利用,结合业务场景和使用情况,需要开发人员确认;而是危害较大,可以参照CVSS3.0的评分,7.0及以上的漏洞为高危和严重,需要被关注。将两者结合,即开发和安全人员配合,才能找出真实可以被利用的组件漏洞。

要想解决修复哪些漏洞的问题,从原则上来说已经有了方向,但是在实际场景中,可能会给安全和开发带来大量的沟通成本,因为开发人员懂业务(组件使用姿势)不一定懂安全、安全人员懂安全(漏洞利用方式)但不一定懂业务。故有必要建立开源组件可利用漏洞库,将高危及以上漏洞的触发条件、利用危害、修复方案提供给开发参考,各业务的相同组件使用方式可能不一样,但是漏洞原理是相通的,可以减少修复工作量并针对性的积累了组件漏洞。

当互联网上传播组件漏洞情报时,如何快速定位哪些业务受影响?基于源代码层面的组件漏洞扫描,可以将代码中使用的组件及版本信息(甚至是多层的引用与包含关系)识别出来,获取这些信息后建立以系统或部门为单位的开源组件资产库,再将受影响的系统直接生成漏洞工单(打通工单系统),可追溯至漏洞闭环。

3.3 安全教育

安全培训,想必很多企业都在做。但是真的有效,并能持续不断的生效吗?安全教育通常都会被理解为安全培训 考试,但即使是考试通过,也不能意味着开发的代码安全。

以安全培训为起点,往前想一想,安全培训的素材来自哪儿?编码安全规范,规范怎么来的?主要通过平时的安全测试结果总结而来,也就是说安全培训的初衷是为了不再有已知的安全漏洞,实际的演进路线是:安全测试发现安全问题-->制作标准与规范-->安全培训赋能。

然培训之后,用考试通过率作为安全培训的指标,并不是最初想要实现的目标,也就意味着这个方案过于单薄,单点发挥的效果不够理想。不可能经常组织考试,考试满分也不能肯定写的代码没有漏洞,毕竟说到和做到有不小差距,考试场景和日常工作也差距较大。不过还有更进一步的方式:把编码安全规范,细化为AST的检测规则,比如常见也是最常用的SAST,维护最小化的有效规则,做到与规范相呼应,保障其落地,还能解决传统SAST扫描结果误报巨大的被动局势。

3.4 开发环境

在供应链攻击方面,除了第三方开源组件外,在开发安全中还需要关注开发者使用的工具、技术和环境。

  • 开发工具:使用官方或企业提供的工具,避免使用论坛中提供的安装包、云盘中的安装软件、破解方法中的破解文件…来历不明情况下,很可能遭受水坑攻击。若在必须使用的情况下,建议先上传VT杀毒或跑在线云沙箱,以初步确定其安全性。另需持续关注官方的安全补丁更新情况,虽然漏洞预警的职责属于安全团队。
  • 开发框架:经常爆出漏洞的开发框架,建议不允许在内部使用,比如漏洞之王- -Struts2,直接拉到黑名单中。另外在框架层面做安全配置,以防御常见的漏洞。比如Django的querysets防御SQLi,模板可以抵御大部分XSS攻击,通过白名单限制允许访问origin头防御CSRF等。
  • 开发环境:JAVA的JDK环境、Python环境等都属于在本地开发时必备的,该部分的安全可交由终端上的EDR防御,或若是服务器上的话,可能就只能借助NTA设备的监测。安全还是需要从源头治理,故在安装这些环境的时候得注意来源渠道和软件的正规性。
  • 网络环境:这一点比较难以做到,即开发环境与办公环境隔离、开发环境与互联网隔离。理论上做到网络隔离,即使开发环境沦陷,也能控制住受影响范围。至于落地情况,每家都不一样,尽可能的做好内部安全域的精细化管理。

3.5 安全编译

这个小实践有一定的局限性,仅适用于使用C/C 的产品开发,但是在我们这种硬件盒子厂商,属于比较常见的安全需求。在使用GCC和VS进行编译时,使用工具提供的安全加固选项,比如加入ASLR(Address Space Layout Randomization:地址空间布局随机化,将进程中的内存空间地址进行随机化,增大入侵者猜测目的地址难度)可以在极大程度上防止缓冲区溢出攻击。

  • 作用选项不同:针对不同的平台,安全编译选项也会有所不同,特别是Windows和其他平台之间的差别较为明显。在这些安全相关选项中,具体的配置选项也有所不同,包括链接选项、编译选项、内核选项、运行系统配置、编译链接选项等;
  • 作用范围不同:尤其要关注对性能影响较大的编译选项,比如FS在运行时会对相关函数的调用进行检查,会影响性能。可以在测试环境中重点进行性能测试,根据结果决定是否应用到生产环境。

3.6 代码保护

对于代码安全的保护,应该覆盖全链路,包括编码时加入安全意识、完成编码时安全存储代码、交付时保护代码防止被逆向或解密。编码安全在前面的环节已经提到很多,这里主要从以下方面来阐述:

  • 代码仓库保护:代码属于公司的数据资产,按照业务重要程度进行分级分库管理,建议将核心业务代码和一般业务代码分开。核心业务代码通过云桌面进行开发和提交,代码不在个人电脑上落盘。所有级别的代码拉取日志,统一接入管理,代码拷贝通过终端DLP监控,建立异常行为监控和分析,及时发现代码存在的风险。
  • 软件交付物安全:在我们的业务场景中,产品会以软件安装包、虚拟机等方式交付。此时客户侧会接触到安装原始文件、安装完成后本地生成的文件,前者可能存在逆向调试的风险,后者的加密算法则会存在一定挑战。常见的安全问题中,硬编码密码、SAST未发现的漏洞等都可能被外部人员发现,故需要从软件保护、交付物安全加固等方面做好代码的保护。
  • 敏感信息泄露监测:公网GitHub敏感信息泄露监控比较常见,开源的工具也比较多,基本能够满足监测代码通过GitHub泄露的需求。但还有通过网盘、码云等其他公网代码托管平台、云文档等途径泄露,自动化程度比较低还是需要人工关注或半自动化。另外内网的wiki平台、员工自己搭建的共享服务,也都是代码泄露的主要战场。

3.7 运营反馈

关于运营反馈,平时讨论的也比较多。这里以一个最常见的场景来举例。当SRC收到高危漏洞时,负责审核的同学会去验证漏洞真实性,若是存在则会联动二线安全运营人员,对该漏洞的攻击路径进行复盘:

  • 系统是否经过安全测试(安全测试被绕过)?
  • 安全测试工具能否检出漏洞(安全测试规则)?
  • 人工安全测试能否发现漏洞(人工安全能力)?
  • 白帽子发现或利用漏洞时,安全设备是否告警(安全检测能力)?
  • 安全设备告警后,是否一线运营人员及时处置(应急响应能力)?

从漏洞的发现到利用点提出疑问,对现有漏洞发现机制和运营检测规则进行检查与反思。针对每一点不足设置提升的目标和明确的计划,做到:

  • 每一个运营阶段发现的漏洞,就是一次提升的机会,向左层层反馈,查漏补缺,持续优化;
  • 明确验证防守能力最有效的方式就是攻击,与其被动接受(监管单位如CNVD通报等),不如主动获取,内部组织开展红队渗透、外部漏洞悬赏等方式。

04

开发安全左移建议

总结一下,每家的开发流程和业务形态不一样,但是要做好开发安全,个人觉得还是有一定的规矩可寻以及借鉴。

4.1 左移是相对的

在被外部爆出漏洞之前,内部组织安全测试,是左移;在被外部爆出漏洞且在媒体炒作之前,通过内部建立完善的公关机制主动出击,对外PR避免公司产生损失,也是左移的体现…因此左移是相对的,左移代表着安全在产品的研发周期及产品的生命周期中无处不在、无处不移。只要是适合发展现状,能解决当前主要问题的安全措施,都是最佳的左移实践。

4.2 贯彻纵深防御

产品安全可以说是企业网络安全的一个缩影,纵深防御的思想同样非常适用于产品研发周期。从最开始的立项开始介入,随后的需求、设计、编码、测试、发布、运营等阶段做出相应安全要求。最开始不用、也不能在每个环节追求完美,想把每个安全问题都检测出来,想要把每个检出的安全问题都推动闭环,而且按照最根本的方案而不是缓解措施,这是很难实现的。大概率会造成ROI低,带来业务方矛盾激化等问题。引入纵深防御的思路,层层设卡与安全检测,在每一个环节解决相对应的top问题,整体效果将会更显著、更上一层。

4.3 安全责任共担

最开始引入“Where Shift-Left”时,就想告诉大家不是安全人员为代码安全买单,而主要问题是出在开发身上。安全人员是有责任帮助开发人员规避漏洞,但主要责任应该归属于开发同学。我们应该以一个教练的角色加入其中,引导开发为自己写的程序安全性负责,提供安全检测工具给他们使用,提供安全咨询服务辅助他们找到真正问题和顺利解决漏洞。安全人员应该是一个教练,而非保姆。“安全责任共担”,是DevSecOps的核心关键之一,在其他开发模式下想必也适用。

4.4 问题抓大放小

当我们将各项安全活动补齐,新上安全测试工具和规则,新添代码审计能手,…会发现漏洞越来越多。这在开发安全初期较为常见,持续一段时间后就会归于平稳。但是这么多漏洞怎么处理呢?全部抓可能接不住或抓不好,不如借助OWASP Top 10的思想,总结内部的top开发安全问题,确定重点解决目标,其他问题同步网格化管理。比如想要消灭SQLi(将漏洞数占总漏洞的百分比降到很低),可以从培训-考核-检测中的每个单方面进行加强。解决完成之后,在第二个问题、第三…直至解决完成。

4.5 安全问题闭环

已发现的安全问题不闭环,Shift Left的效果将大打折扣。更何况还有一些没有被发现的问题,更不能谈到闭环。所以推动已知问题被解决,是一件高价值、理应做得好,却又不好做的任务。比如以安全漏洞为例,各种AST扫描出的漏洞如何管理好呢?一般会遇到这些场景:

  • 开发流程中发现的漏洞,好闭环。在发布前有卡点、有红线要求,不用太担心不修复。不过,也会有绿色通道的情况,即业务需求大于已知高中危漏洞带来的影响,先上线再修复。
  • 运营阶段中发现的漏洞,难闭环。特别是内网环境的高危、可利用漏洞,团队开发了精准的POC扫描,轻而易举的扫出很多高可用漏洞,但是在推动修复时却举步维艰。

经过不断摸索,一致认为走技术已经到头,要想做好漏洞运营工作必须加入管理方法。此时借助了安全管理委员会的力量,由委员会主任组建了内部的安全问题响应群,将公司董事长、总裁、各部门的一把手和安全接口人都拉到群中,每日对超期未修复的漏洞进行公布,并按照部门排名,还时不时的在群里点名,久而久之总裁也在群里点点名,甚至发明和推动了漏洞安全风险分数的落地,整个群一下子就活跃起来,各部门的修洞速度也节节攀升。关于漏洞风险分数有如下内容:

  • 计算公式:安全漏洞风险分数=高危漏洞数*10*时间(超期未修复天数) 中危漏洞数*3*时间(超期未修复天数) 中危漏洞数*1*时间(超期未修复天数),漏洞数后面的数值代表权重,超期表示不同漏洞级别有对应的修复时间,内部安全测试发现的漏洞修复时间要求低于外部从SRC收到的相同等级漏洞,比如安全提测发现的高危是1个工作日时限、SRC收到的高危是12h内须完成修复并上线。
  • 充分落地:前期漏洞风险分数从无到有,起到了巨大的漏洞闭环推动作用。但是时间一长,即使有领导的点名,也会出现部分较长时间未修复的情况。于是又增加了一个指标—高危漏洞最长未修复时间,将以前的漏洞风险分数排名榜中,重点标记这个新指标,大家的注意力有会集中到标亮的指标上,又推动了那部分漏洞的整改速度。由此可以总结出,分析未修复漏洞的数据,找到这个可以用作抓手的指标,单独拿出来计算或排名,不断变化和完善。
  • 指标升级:截止写这篇文章为止,又和领导沟通出漏洞闭环的新玩法。先分析漏洞为什么不按要求被修复,应该是部门领导不重视。为什么不重视,因为这件事儿没让他们心疼或肉疼。于是总裁拍板一个漏洞风险分,让相关部门扣100元部门预算到网络安全部。至于效果怎样,还在推进中,不过阻力不小,但是结果应该不会差。

4.6 安全运营反馈

要想做好开发安全,人工运营是必要条件。主动发现人员、工具和流程上的缺陷并提出优化意见,用安全把产品研发周期和产品生命周期管理串联起来形成一个闭环。运营阶段的安全问题向左反馈,提前到研发周期中解决;开发阶段未完全解决的问题,在运营时设置防护和监测措施得以缓解。

05

开发安全能力输出思考

在开发过程中,发现安全问题为第一步,推动其闭环为第二步,让开发尽可能的把精力和时间放在业务功能实现上、且编写出安全的代码,这是第三步。通常我们找出问题、推动修复会给业务带来不少的麻烦,简单来说修复漏洞就要花费大量的时间。原因可能有:

  • 问题修复方法被绕过要重修
  • 同类安全问题的排查与修复
  • 修复完成后要重新提交功能和安全测试
  • 修复方法引入新的安全问题还要再做一遍以上操作…

如果是有能力的安全团队,可以做更多的事情,比如:

  • 输出安全SDK,提供给业务方使用,被发现漏洞时快速标准化修复漏洞,在编码时杜绝已知漏洞;
  • 输出IDE安全插件,提供给开发同学在编码时,及时发现安全问题并完成修复;……

然而,该部分也在努力实践中,后续有进展再继续做分享。


0 人点赞