前言
笔者在实施SDL方面有多年的经验,实施过微软厚重的SDL,实施过互联网企业粗糙的SDL,目前在落地标准化自动化的SDL,在此将我的经验分享出来。为了让大家更好的理解SDL实施的过程,本文尽量以口语化叙事的方式描述SDL实施的过程。当然每家公司的devops和实际的开发流程不一样,所以实施SDL不能照搬照套,还是得结合自己公司的实际情况。
越来越多的安全招聘JD要求会SDL建设,比如安全负责人、安全专家、web安全等。很多企业招聘JD写了要求会建设SDL,但是他们对SDL建设的目标可能不太清楚。或许有个模糊的概念SDL是保障开发安全的,只是看到别家在招聘SDLer所以自己也要招个SDLer。甚至面试的时候压根不会问与SDL相关的任何知识,等真正开始着手建设SDL的时候就是摸着石头过河,很容易被微软厚重的SDL建设思路带偏。
一、 企业为什么要做SDL?
我们熟知的安全防御手法大多是边界防控,例如对外通过反向代理只开放80和443端口,一般还会在反向代理后面串行一个waf做攻击拦截。
边界防控实施起来比较容易而且安全收益也非常可观,所以是企业建设初期必做的事情。但是对于正常开放出去的服务如何保证它的安全呢?传统的做法是在产品上线前经过安全测试或者安全扫描,这种做法比较局限。首先安全人员的测试水品参差不齐很难测全,其次很多公司的测试环境与线上环境区别较大,在测试环境测试完后往往没有发现漏洞上线后却被黑客利用了。另外,上线之前发现安全问题其实是比较滞后的,这个时候再去修改问题成本比较高。众多的产品线只能靠投入人力资源去跟踪测试,这个成本也是相当高的。
SDL将安全活动嵌入到整个研发流程中去,从立项需求评审、开发代码扫描、测试漏洞扫描、发布基础环境检查、上线实时安全监控与检查这些环节逐步保证研发流程的安全,做到尽可能将安全问题往前移,建立流水线的日常安全任务保证安全横向(全面覆盖所有的研发项目)、纵向(对一个研发项目各个环节加入安全检查)的覆盖率。
流水化、标准化、自动化才能保证更高效的解决研发的安全问题。
二、 微软如何实施SDL
下面是一张只要讲SDL就必须贴的图。这个是微软官网上的一张SDL实施流程图。很多互联网企业实施SDL会严格按照这张图来,最后导致因为实施起来太繁重而不得落地。甚至据我所知很多乙方企业在给甲方提供咨询服务的时候也会严格按照这个流程来讲,这真的是只知其形不知其神。
微软的SDL实施比较厚重,并不太适合互联网企业。从下面的实施步骤中可以看出,微软的SDL的实施步骤都是一环扣一环而且每一环的而且实施周期长、参与人员多、实施的技术要求高。对于微软这种软件供应商来说这种SDL实施是适合的,比如像word这样的产品需要成年累月的时间才能完成开发,那么安全在这个过程中就能占据稍微多点的时间把握每一个步骤的安全性。但是对于互联网企业敏捷开发和高迭代明显就不适合了。
以下是微软SDL实施的步骤以及特点:
1、安全培训
微软对于一个项目开始实施SDL之前一定要做安全培训,培训要求参与人员多,而且培训周期长,如果互联网企业这么做势必会拖延项目周期。
培训对象:开发人员、测试人员、项目经理、产品经理
培训内容:安全设计、威胁建模、安全编码、安全测试、隐私等
2、安全要求
项目确立前与项目经理或产品所有者进行沟通,确定安全的要求。
3、安全和隐私风险评估
安全风险评估(SRA)和隐私风险评估(PRA)用于确定软件中需要深入评析的功能环节。包括 ① 项目的哪些部分在发布前需要建立威胁模型?② 哪些部分在发布前需要进行安全设计评析?③ 哪些部分需要由不属于项目团队且双方认可的小组进行渗透测试?④ 是否存在安全顾问认为有必要增加的测试或分析?⑤ 模糊测试的具体范围?⑥ 隐私对评级的影响。
4、威胁建模
微软的威胁建模推荐STRIDE 模型,但是这仅仅也只是一个模型而已,威胁建模对人员的要求很高,必须懂很多方面的知识才能做好威胁建模。举个例子,现在对一个区块链系统做威胁建模,但是如果安全人员连区块链都不知道是什么那么就算再会用STRIDE 模型评估出来的安全问题也是比较浅显的。另外威胁建模需要深入了解业务,需要业务方一起参与进来,对于时间消耗和人力消耗比较大。
5、静态分析
这里静态分析就是代码审计,一般是多方人员参与审计,审计周期较长。
6、模糊测试
做完代码审计后难免也会有遗漏所以还要做一个黑盒测试,微软采用的是大规模发送fuzz数据测试系统的安全性。
7、上线,应急响应
留下第三方联系方式运维同事,网络监控同事,并加入到应急响应计划中来。
三、 互联网企业如何实施SDL
很多人理解SDL就是个流程,不错流程确实是SDL中的一部分,但是SDL的流程需要达到一个什么样的目标,以及达到这样的目标需要什么样的技术支持,可能主动去思考的人不多了。
SDL设计图
实施SDL想要获取一个比较好的收益,公司的devops建设的越完善越好。SDL流程一定要跟devops很好的契合起来这样才能达到最大的收益比,这也就是为什么小公司不建议做SDL。如图所示SDL就与devops紧密结合起来的。
为了有效管理项目的开发周期内各个阶段面临的风险和自动化识别风险,我们将SDL平台设计成两大部分。
SDL平台主要分为两大部分:项目与风险管理、风险识别系统。
项目与风险管理部分,该部分会以项目为维度将一个项目的风险贯穿到需求、开发、测试、发布、运行这几个阶段,在每个阶段我们可以清晰的管理存在的风险和修复情况。
风险识别系统部分,该部分分为三大块,在开发阶段CI/CD构建之后会主动触发代码扫描引擎进行代码风险扫描,在测试阶段CI/CD集成测试会将流量重放到灰盒扫描平台做到实时自动化漏洞扫描,在运行阶段各种监控和检查系统会实时汇报项目的健康状态。
1、安全培训
在微软官网上实施SDL第一个步骤就是要做安全培训。那么对于互联网企业产品迭代快,推崇敏捷开发,在产品开发前把产品经理、开发、测试召集一起做个安全培训合适么?显然不适合,相信没有一个互联网公司愿意这么做,这样太影响研发效率了。这个时候我们就要借助外部资源了,比如有些互联网公司每个月都会举办一次技能培训,这个时候安全开发培训可以穿插进去,有些公司有内部的学习网站也可以上传安全开发教程。
培训内容包含:安全开发规范、漏洞原理和危害知识科普、安全部门的管理制度、安全红线等。最好是能跟公司的考试制度结合起来,这样才能更好的巩固大家的安全知识。也就是说我们的安全培训是常规性的工作,而不是在一个项目开始前一定要进行安全培训。
2、需求评审阶段
在笔者看来这个阶段才是SDL实施一个项目的真正开始。
在微软的SDL模型中是将需求和设计分开的,但是这里选择将两者合并。
这个阶段要解决以下问题:
1)对于互联网企业立项多需求多,如何第一时间捕获到这些立项信息?如何集中化管理这些项目信息?
由于这个问题的出现,SDL平台也就孕育而出了。在这里我们将SDL流程分成5个节点。正如上面的SDL设计图所示,SDL平台会定期同步最新的项目需求,安全人员可以第一时间去跟进项目。
2)对于互联网企业需求如此之多,安全评审如何做到有效覆盖?如何将安全与业务解耦出来,避免安全人员将更多时间投入到业务了解上?
有些互联网企业按照产品线投入安全人员去参与现场需求评审,但是这么做想要覆盖如此多的项目还是比较吃力的,需要投入较多的人力,需要深入了解业务逻辑比较花费时间。这个时候我们就需要根据公司的业务特征提炼出安全风险检查checklist。这里我根据我们公司的业务特征梳理出了认证、授权、访问控制、传输安全、加密安全、日志审计安全、数据安全等这些大项,大项里面包含一些细分的小项。当我们获取到项目需求之后SDL平台会自动发送安全评审checklist给业务团队,业务团队填写完安全评审checklist之后,安全团队成员可进一步评估。如果发现有异常项再跟业务团队沟通,确实存在安全风险就提交给业务方进行整改。在这里要强调一下,我们可以事先在SDL管理后台预置一些场景名称与对应风险的威胁建模列表,发现风险后安全人员只用拖动场景名称标签来生成风险列表并自动知业务方进行整改。
3、开发阶段
开发阶段采用独立的代码扫描引擎对接CI/CD,SDL平台只做项目与对应代码风险的管理工作,并由代码扫描引擎将漏洞代码同步给SDL平台上开发节点进行展示。当开发流程进入到CI/CD的开发节点的时候,CI/CD会调用代码扫描引擎的接口告知扫描对应项目的代码仓库。
在这个阶段主要考虑的是代码扫描准确性的问题。常见的代码扫描器有fortify、checkmarx这两款都是优秀的商业版静态代码扫描器。Fortify扫描基本原理是把各种语言的源代码转为一种统一的中间语言代码,基于语法语义和规则进行代码扫描,对数据流分析主要负责收集代码中的变量传递流向,同时收集变量的净化情况。根据中间代码分析代码漏洞,并得出报告。Fortify在输入源和危险函数识别上还是比较准确的,但是参数净化识别这块却有些无能为力。如下图如果intval是自定义函数,fortify根本没法识别出来这个参数是否真的有效过滤了,因此这也是fortify产生大量误报的来源了。另外fortify也不支持灵活的代码规则编写,在发现新的漏洞的时候也无法编写规则造成许多不便利。
根据笔者的实践结果也验证了采用fortify扫描代码会产生大量的误报,大量误报的代码风险推送给业务方会造成业务方的忽视,同时也影响了安全部门的权威性。因此对于安全风险的推送有个原则宁愿漏报也不要大量误报。对此,我们采用的基于正则的代码扫描引擎,在另外一篇文章中会有详细介绍。
简单介绍下这个扫描引擎的优点
1)代码开源可以二次开发无缝对接CI/CD。
2)自定义扫描规则,可以针对公司业务特点制定代码扫描规则。3)通过自定义规则可以控制扫描出现较低的误报。
当然缺点也很明显,扫描引擎是纯规则匹配没法理解上下文语义,但是没关系最重要的是扫描出来的风险要准确。我们可以扫一些代码规范类的问题。例如:不规范函数、SQL语句拼接、redis和 MongoDB未授权访问、数据库连接信息硬编码、DEBUG 模式未关闭、fastjson远程代码执行漏洞特征代码…… 虽然扫描来的这些问题不一定是漏洞但一定是代码风险和不规范的写法,这样业务方也更容易接受整改。对于检测有明确漏洞的代码可以交给运行态代码检测工具iast去发现。当然这个阶段如果是核心业务也可以介入人工代码审计。
这个阶段还有一件重要检查要做--漏洞依赖检查。
对于一个java应用肯定会有各种各样的依赖jar包,常见的漏洞依赖比如struts漏洞的commons包,fastjson漏洞的依赖包。这里我们采用的dependency-check,这个工具会通过mvn命令解析代码中的所有依赖并和漏洞库的依赖版本进行比对。这里有个问题需要解决,代码中很多依赖是底层依赖,牵一发而动全身。底层依赖在单个项目中进行整改难度较大,所以我们需要对漏洞库进行梳理。对于底层依赖要做专项整改,对于上层依赖可以在单个项目中升级。
4、测试阶段
同样这个阶段将使用独立的漏洞扫描引擎对接CI/CD,SDL平台只是做项目与对应漏洞的管理工作,并由漏洞扫描引擎将漏洞信息同步给SDL平台测试节点进行展示。当开发流程进入到CI/CD测试节点的时候,CI/CD会将流量重放到漏洞扫描引擎进行扫描。
这个阶段同样存在扫描准确性的问题。对于传统的黑盒扫描AWVS、APPSCAN、自定义的基于poc的扫描都存在扫描误报的问题。这个在做自动化扫描的时候由于误报信息太多也不被业务方接受。
那么这里我采用的是IAST灰盒扫描,在我的另一篇文章中有介绍这里不赘述。IAST原理分析以及在SDL中的应用
5、发布阶段
如果公司是容器化部署,在发布阶段会进行镜像基线检查。这里会调用harbor接口检查仓库的镜像安全性。
如果是虚拟化部署,在发布阶段会进行系统基线检查。这里可以使用nessus或者HIDS进行检查。
同时在这个阶段也会对前面阶段所发现的问题进行拦截不准发布。我们定义的拦截标准有权限提升漏洞、资损漏洞、数据泄露漏洞、其他高危漏洞。
6、上线阶段
上线阶段主要做的事情是安全检查、安全监控、情报收集。
应用方面检查:将url添加到黑盒扫描系统进行定期扫描。
系统方面检查:nessus定期扫描系统漏洞,harbor定期检查镜像漏洞。
代码方面检查:阶段性对线上仓库的代码进行代码扫描,同时跟新代码扫描规则。
waf安全监控:定期关注waf拦截信息。
ids安全监控:查看内网异常流量。
hids:查看服务器异常进程、文件信息等。
四、 SDL建设的目标
自动化和高覆盖率:SDL平台能实时获取各业务方的立项信息,自动化通知业务方完成安全风险检查checklist,进入到CICD流程能自动化进行代码风险扫描、自动化进行漏洞扫描,对于发现的高危风险在发布的时候能进行拦截。
标准化:根据项目的人日和重要等级进行排序优先将安全资源投入到重要项目。对于SDL各个阶段制定安全风险等级,超过风险等级的项目禁止发布。对于需要进行人工安全测试和代码审计的重点项目,要按照事先制定的安全测试标准和代码审计标准进行,防止有遗漏的测试项。
准确性:SDL中的代码风险扫描和漏洞扫描两个引擎要保证扫描的准确性。在这当中代码扫描规则是自己编写的可以保证准确性,iast扫描是基于上下文语义分析可以做到0误报。
*本文作者:hackeryeah,转载请注明来自FreeBuf.COM