文/平安银行应用安全团队@贾凯
前言
17年起,我们引入建立了适合内部研发的SDLC流程,在传统的研发模式下,一个需求从意向拆分到用户故事,再到开发子任务,一次迭代大多都要经过2周以上的时间。经过重人力运营的严格SDLC活动(各业务开发条线配备一名或多名专职安全运营人力进入开发团队深度运营),完成下来基本上可以极大的降低应用安全风险。但随着这两年公司IT人力迅速扩张,以及各类业务需求的爆发增长,推动着敏捷开发的迭代周期不断缩短,倒逼研发模式向DevOps转型。这种状态下,重人力运营的SDLC逐渐成为整个开发流程中的短板,对于动辄数千个应用的组织来说,也只能挑选重要的业务系统执行SDLC,大量内网应用无人力覆盖,而且在新时期对更频繁、快捷、可靠以及智能的要求下,愈发凸显出这种模式的缺点,由此必须转变思维,建设在敏捷模式下的广义应用安全体系。
SDLC模式
SDLC是定义在安全团队及研发团队共同配合下的安全活动,在对需求做完安全评审以后,除了最终需要安全团队执行的安全测试外其余都需要研发团队独立完成。
**安全需求识别:**研发团队架构师识别哪些需求是涉及到的安全。
**安全设计环节:**安全团队针对开发子任务给出指导性安全checklist,开发团队针对涉及到的接口做安全设计。
**安全设计审查:**开发团队架构师对安全设计做审查,评估安全设计无问题即可进入正常编码环节。
这几个环节下来,如果由开发完全独自执行,对于安全意识不够强的研发同事来说,安全设计的质量无法保证,这个时候基本上是安全团队在测试过程中对发现的安全漏洞进行溯源,定位安全设计及审查环节的问题,做常态化的检查。
在重要系统实践了一个时期后,绝大数研发团队的安全意识及安全编码能力得到了极大提升,遗留到测试环境下的漏洞数也大幅减少。当然,SDLC的推行需要领导的大力支持。
但在实践中也发现存在一些安全设计质量不佳的情况,仔细定位下来发现基本上是:
1、新入职的员工即使经过强制安全培训后,安全设计及安全编码依旧质量不足;
2、研发团队懈怠情况。
为此我们建设了漏洞积分,每个漏洞关闭时都必须对应到漏洞开发人员/小组/部门,积分到达一定限度后,强制进行安全考试,回炉接受再教育再次进行安全培训(类似驾照违规重新考试)。
此外依据这些数据对研发团队针对性的培训宣导,持续根据执行结果进行周期回溯检查。
DevOps下的应用安全管控体系
在以上的模式下,互联网的业务系统经过严格的SDLC后再进行发布,安全问题得到了保障。
但随着执行经验的积累,问题也随之而来:
1、如开篇所说,在向DevOps转型的过程中,动辄每周1次或多次的发版频率下,安全人力介入作为开发流程中关键的节点显然成为了瓶颈,业务需求的快速增长给人工评审及人工安全测试带来巨大压力;
2、在人力方面,显然不可能无休止增加投入,更重要的是安全工程师水平差异导致各业务线的安全性差异,人永远无法作为一个衡量安全管控标准的尺度;
3、虽然互联网应用已用此方投入大量人力堆了下来,但面对规模更大、更复杂的内网应用怎么管?用脚想也不能生搬硬套;
4、理想状态下SDLC应该是研发团队自驱执行的,安全一直在深度介入、带领的安全开发流程,不利于研发团队安全能力的长效实质提升,可能安全工程师一松懈,安全执行标准就下降。
所以当安全把控的效率及覆盖面上有了更高要求时,要根本解决这个困境,首要的是改变环境,通过安全基建去创造优化安全开发的环境,重新设计构建适用的应用安全管控体系。
“要求—检查—管控—防护”
从应用的整个生命周期来说,这是应用安全管控的主干思维流程,应用的变更大部分都体现为需求,在对研发流程上各类纬度的要求都可以体现在对需求的要求提示上。
整体的建设思路可类比为现代化交通治理的逻辑,将应用的构建、测试到发布线比作一条高速公路:将安全介入执行的SDLC比作载客大巴,安全是司机;将开发团队独自执行SDLC比作自驾;应用安全的执行要求是交通法规;检查手段是高速上的各类传感器(测试器、探头等);管控手段是上高速的收费站,也可以是驾照的扣分制度;防护手段即是高速上的应急车道…如何保证高速公路上车辆有序、高效、安全的行驶,即是我们应用安全管控体系建设运营的启发参照。这么一想,豁然开朗…
执行要求
执行要求中,不论是作为SDLC中接口安全设计checklist要求,或是数据共享管控要求、隐私合规要求、监测埋点需求等其他广义上的各类研发要求,这些都可以作为提示项,放入需求阶段(研发管理平台)或者接口设计阶段(接口管理系统)中的安全提示。
在内网应用需求上提供基于问答式的安全自检解决方案,后期可以做到更加具体细致,对涉及尽可能多的场景抽象出一些需求场景的评审checklist。
编码阶段
接口设计中,将SDLC涉及的接口安全checklist作为接口设计(新增/修改)的必要属性。
使用内部嵌入安全组件的开发框架,例如将esapi改进为适合内部框架的安全组件集成到开发框架中,供开发自行选择使用。
在编码环节,提供嵌入IDE的安全编码助手插件(开源工具二次开发改进),供开发人员自助进行代码扫描,前移代码扫描环节。
测试阶段
在DEV/SIT测试环节,提供浏览器插件,供开发/测试人员自助进行动态扫描,前移动态扫描环节。
检查阶段
检查手段是关键一环,需要做到有要求必有检出的能力。
这里需要建设一系列检查手段,包括SDLC执行规范质量检查、基于流量的DAST、基于堆栈的IAST、基于代码的SAST、基于包库的组件及依赖检查、人工安全测试的五种检查手段。
通过splunk自动化分析SDLC执行规范、制定违规通报。
DAST被动+主动式的动态扫描器(主动模式下,积累归集流量中采集到的报文,替换登录态随时执行主动全量扫描),可参看之前文章《被动式漏洞扫描平台建设之路》。
SAST嵌入到CI流水线任务下的静态扫描器,确保每次git的代码提交都经过安全检测。
【存量及增量控制】
建设另一种思路下的IAST能力,与APM监测工具合作,记录堆栈数据,离线准实时检测安全漏洞,可参看之前文章《企业快速部署IAST/RASP能力的一种新思路》。其中在被动扫描器+IAST的模式下,可以做到部分场景下越权漏洞的检测。(2次替换cookie发包,对比带入的sql语句)
建设解决增量及存量的组件安全依赖扫描能力,可参看之前文章《通用组件安全治理三步走实践》。
在人工测试环节,对于重要应用的重要需求流转到人工测试环节,执行安全测试任务。
还需要做到的是,在自动化检查工具中增加实时提醒的功能,通过跟接口平台联动,将检查内容与要求挂钩,将安全整改工作尽量左移,一旦检查出不符合要求的点,可以立即通知到相关责任人进行整改,在卡版前给出研发整改时间。
管控阶段
通过检查过程中发现的问题,将检查结果数据跟各纬度的SR/SST/版本对应起来,存入安全运营平台中,这样就形成了版本—风险值的维度,初期我们定义一些简单的卡版规则,对不符合要求的版本卡发布,例如中高危漏洞不可发版,没有接入SSO不允许发版等。在持续建设后期可以根据各类安全规则给出版本的安全评分及安全检查报告,执行更精细的版本安全管控。
此外我们还需要一个基础应用安全元数据系统(通过同步运维、架构的全部应用基础数据),可以将检查结果对应用打上各类安全标识,为长期的应用安全治理工作打好基础;结合安全运营平台,更便捷地对各类安全漏洞、安全整改项做闭环跟进处置。(这里要感谢运维及架构兄弟们的支持,企业安全的建设水平非常依赖于组织内部运维及架构上的建设水准,这就类似高速公路上跑的各类汽车,运维架构标准化覆盖率上去后安全的建设水到渠成。)
防护阶段
应用发布后,研发流程的工作就告一段落,我们就需要对线上潜在的攻击行为做预警响应处置。
建设基于流量的入侵检测能力,流量安全分析,我们熟知的XX眼、各类WAF的日常运营。
建设传统的HIDS,我们熟知的XX云等日常的安全运营。
建设基于堆栈的攻击告警(RASP),这里因为我们的实践思路是通过采集应用堆栈日志离线分析,所以只是做攻击行为告警,之后再进行人工处置(跟正统的RASP思维来说差距就是实时阻断的能力,对传统金融行业的业务系统来说,实时阻断还是有些压力的,我们的方案只做堆栈埋点,在日志消费速率足够的情况下,做到实时攻击行为告警,之后人工处置。对这部分如感兴趣,可参看之前文章《企业快速部署IAST/RASP能力的一种新思路》。)
建设新增资产监控及常态安全巡检,掌控全部的应用资产,确保不会遗漏安全死角,新增应用及映射定时通知安全运营人员,确保得到把控。
建设最新的通用型安全漏洞预警,面对新出的安全漏洞时及时的分析对公司资产的影响程度。
总结
到此为止,我们从SDLC的思维模式逐步转变为全生命周期的广义应用安全管控体系。
建设这个体系后,带给我们几个提升:
1、 提升了安全工作的覆盖面及安全运营效率,从针对重要应用的安全运营工作转变为对全部应用的体系化安全管控,无论是外部还是内部应用皆在安全运营范围内。
2、 安全管控线上化标准化,在与测试及发布工具联动后,从依赖“人工版本把控”转变为依靠“系统判断”进行版本安全的管控。
3、 从传统应用安全管控的角度转变为广义安全管控的角度,只要涉及研发流程,皆可通过这个模式来实现“要求—检查—管控”的整改落地(也可解决安全以外的研发整改问题),各类研发的整改皆可通过各类检查 + 跟进闭环 + 版本管控 来实现“消化存量、管控增量”的目的,这个是非常重要的。
4、 体系化提升,通过检查阶段的结果,反溯研发过程,给出各部门排名,从管理手段上提升研发同事的安全能力,安全更加可控。
5、 不再仅限于发布前的应用安全管控,而是贯穿了应用全生命周期的安全管控体系。
等等,很香。
对一个大型的IT组织来说,在后续的运营过程中,我们还需要不断拓展我们的覆盖面,以及不断优化我们的检测深度,还有很多的路要走。