企业DevSecOps流程建设之工具篇

任何一个安全项目或体系的建设始终围绕着三个核心点来进行:组织,流程,工具:

  • 组织:确立项目目标和建设实施团队
  • 流程:建立制度,明确各方责任
  • 工具:支撑流程的运转

本文着眼于DevSecOps流程建设中所使用的工具,暂时先不讨论其他两个点。

引言

在讲究小步快跑和快速迭代的互联网企业里,效率的优先级要比质量高,在发展中解决质量问题是大家的共识。这种观点在书本《Google系统架构解密》[8]中是这样评价的:

区分初始速度和持续速度是很重要的。在项目初期选择不考虑安全性、可靠性和可维护性等关键需求,确实会提高项目早期的速度。然而经验表明,这样做通常会在项目中后期显著地拖慢进度。为了适应涌现特性的需求而重构设计的后期成本可能非常高。此外,为解决安全和可靠性风险而进行侵入性的后期更改本身可能会带来更多的安全和可靠性风险。

结合我在互联网企业里的项目开发经历来看,在没有建设好安全文化和流程(换句话说,不重视安全)的互联网公司里,传统的SDL流程还是稍显笨重。如果真的强求每个项目都在立项之处就从安全威胁建模做起,光是安全团队的规模就很庞大;另一方面,追求项目快速迭代的团队也不希望被团队外的安全人员卡点。目前来看,应用安全建设里最可靠的方法还是建设好DevOps的工具链,在工具链里融入可以高度自动化的安全测试工具,在项目的编码,集成,发布和运行阶段都进行安全测试并提供足够的安全故障自助处理工具让开发人员将项目的安全水位提升到及格线之上。

DevSecOps流程建设

建设DevSecOps流程需要一个体系化的建设思维,现在随便谷歌一下也能找到一大堆解决各个单点问题的开源工具,但我觉得要真的做好DevSecOps流程建设,需要把握几个关键点:

  • 全局把握安全建设的重点方向和节奏,了解清楚各个单点问题的轻重缓急,先做哪个后做哪个其实很重要,毕竟企业愿意往安全方向投入的资源本来就很少,如何用很少的资源去支撑整个安全团队的持续发展也是一个需要思考的问题。
  • 如何将各个单点工具串联起来并自动化运营,也就是所谓的安全编排,毕竟工具越多,告警越多,需要投入的安全人力就越多。如果没有自动化运营的能力,搞到最后就会出现部署一大堆东西但是没人管的局面。

首先思考代码的漏洞来自何方,我们才能知道究竟要解决DevOps中的哪些安全问题:

  • 编码过程引入的漏洞
    典型的例子是后端程序在接收到参数时直接拼接成sql语句执行,很容易就会遭到sql攻击
  • 代码中引入了开源组件中的漏洞
    如fastjson,log4j等应用非常广泛的第三方组件在你使用的时候是安全的,但保不准哪一天就会爆出致命漏洞
  • 代码的运行环境配置不正确
    没有遵照代码运行环境(包括容器,云上和云下的服务器)的安全基线来配置启动参数
  • 供应链被投毒
    简而言之,就是第三方供应商提供的软件/硬件里包含了漏洞,譬如dockerhub上的投毒镜像

工具建设

首先看一下DevSecOps流程中每个环节要用到的工具,如下图所示:

图中对应的四个阶段分别是:开发,集成(代码编译,生成镜像),发布(推送到运行环境)和运行。本章节会先介绍上图中经常出现的SAST,DAST,IAST这三个极其容易让人混淆的概念,然后再比较IAST与RASP的关系,最后介绍SCA,至于代码质量管控,威胁建模和镜像扫描则不在本文中介绍。

AST

AST类工具是测试工具,并不是漏洞挖掘工具。

  • SAST(Static Application Security Testing,静态应用安全测试):SAST是白盒测试(可以看到应用的所有源码)的一种。简单来说,就是在应用编译前进行源码扫描,特点是误报率高。最好的实现方式是开发IDE的插件,以便开发人员在编码的时候就可以直接检测代码;另外,也可以把安全编码规范融入到IDE的插件中(例如Alibaba Java Coding Guidelines),这样的做法要比对开发人员进行线下编码规范培训的效果好。

  • DAST(Dynamic Application Security Testing,动态应用安全测试):DAST是黑盒测试(看不到应用的源码)的一种,简单来说,就是先把应用运行起来,然后不断地输入各种测试案例,通过观察生成的输出来判断是否有漏洞,常见的web扫描器就是DAST的一种工具。

  • IAST(Interactive Application Security Testing,交互式应用安全测试):IAST是灰盒测试的一种。(灰盒测试就是你能定位到代码问题的精确位置,譬如哪个源码文件的哪一行,但是你并不知道是什么原因导致的;白盒测试就是打开整个项目的源码,通读代码后找出导致这个问题的原因;而黑盒测试就是在项目运行的时候跑了一大堆测试后看到输出结果不正常,至于错在哪里,怎么错的一概不知)通过部署在服务器上的agent收集应用运行时的各种数据(接收到的请求,执行的函数,传递的参数等)来判断是否有漏洞(参考下面的洞态 IAST),如果想要做得更加精确,可以将业务请求放到扫描器上重放(参考下面的Baidu openrast-iast)。

三者之间的关系
从下图中的左边部份可以看到SAST与DAST演化出了IAST,而WAF和IDS/IPS技术则逐渐演化出了RASP(在下一小节会介绍)。

三者之间的关系

下面通过两个IAST的开源产品来分析一下它的工作原理。

洞态IAST,它的产品文档里的原话是这样描述的:

IAST 相当于 DAST 和 SAST 的组合,是一种相互关联的运行时安全检测技术。它通过使用部署在 Web 应用程序上的 Agent 来监控运行时发送的流量并分析流量流以实时识别安全漏洞。
三者的区别

其实我觉得IAST算不上是DAST和SAST的组合,这是三个不同功能的产品,并不是说有了IAST就可以替代SAST和DAST了。结合上图再重新看我对IAST的概念解析就一目了然了。

再看其架构图[8],原文如下:

首先,在服务器上安装 IAST Agent。当 IAST 启动,用户访问 Agent 服务后,Agent 便开始采集数据,并与 OpenAPI 服务通信,进行上报数据和 Hook 规则的拉取。OpenAPI 将数据存储到数据库中,包括 MySQL 和 Redis。
然后,Agent 对 Engine 发送通知,Engine 便会来消费数据库中的数据,并在分析(漏洞分析原理)完毕后将漏洞信息回写到数据库中。
最后,用户通过 WebAPI 查看数据库中漏洞的数据信息。
洞态IAST架构

百度 openrasp-iast ,关于系统架构的原话:

IAST(交互式扫描)技术是一种实时动态交互的漏洞检测技术,通过在服务端部署agent程序,收集、监控Web应用程序运行时函数执行、数据传输,并与扫描器端进行实时交互,高效、准确的识别安全缺陷及漏洞。目前OpenRASP项目已实现相当于IAST agent端的OpenRASP agent,在此基础上引入一个扫描端,即可实现一个完整的IAST扫描工具。

从架构上可以看到它跟洞态 IAST 的不同之处是引入了一个扫描器来对每一个正常的业务请求进行流量重放。

RASP

RASP(Runtime Application Self-Protection,运行时应用程序自我保护),其运行原理如下图所示:
RASP技术原理

  1. 收集数据:在运行APP的服务器上需要部署一个agent,这个agent会将防护功能”注入“到应用程序中,与应用程序融为一体。这里所谓的“注入”在不同的开发语言中会有不同的实现,以java举例,它的实现方式是通过Instrumentation接口(java.lang.instrument)编写一个agent,在 agent 中加入 hook 点,当程序运行流程到了 hook 点时,将检测流程插入到字节码文件中,统一进入JVM中执行(更底层的实现原理参考这里)。既可以在APP运行前就注入,也可以在APP运行时注入,尤其是运行时注入的能力提供了在APP不重启的情况下进行漏洞热修复的功能。实现原理如下图所示:

  2. 阻断执行,agent还可以根据请求的参数和应用运行时的上下文(堆栈信息)来判断是否需要阻断该请求。RASP一般都会拿来与WAF(Web Application Firewall)进行比较,因为WAF也是在APP处理请求前先过滤掉请求,但WAF只能通过检测流量的特征,而不能获取到应用运行时的上下文,所以会造成很多误报。同时WAF严重依赖于恶意流量的特征库,只要特征库更新不及时就很容易被绕过。举例来说,log4j漏洞在刚爆发时,短时间内就出现了很多poc,WAF是很难及时将全部poc都同步到规则库中;并且攻击者可以通过流量混淆工具来隐藏恶意poc,导致WAF出现误报和漏报。但是RASP就可以很好地处理这个难题,因为只要agent检测到log4j漏洞使用的JNDI的框架,就可以结合上下文信息来判断是否需要停止应用的业务响应流程,从而拦截恶意请求,如下图所示:

RASP的开源产品有百度 openRASP,上面提到的百度 openrasp-iast 就是在此产品的基础上添加了一个扫描器而成,由此可见 IAST 与 RASP 的紧密联系。

Q:是否有了RASP就完全不需要WAF呢?
A:我认为二者是互相补充,而不是替代关系。RASP的确可以比WAF看到更多的信息(如下图所示),但并不是所有的应用都可以通过RASP来做保护,目前RASP最广泛的应用场景还是在java语言开发的APP上;另外一个问题时RASP对APP造成的性能影响你又是否能接受呢;并且万一RASP引入了新的故障点,谁来负责处理也是个问题。

额外提一下,我认为RASP在一种特殊场景下会比较有用,那就是保护那些已经运行很久的遗留项目或者是没有源代码的第三方项目,并且这些项目对性能的要求并不高。


最后展示一下这四个工具在DevSecOps流程中发挥作用的阶段,如下图所示[1],其中圆点的实心比例表示工具的自动化程度:
DevSecOps 安全工具在不同阶段的自动化程度

至此,已经介绍完了DevSecOps里常用的几个漏洞测试工具,下面继续分析剩余的其他工具。

SCA

SCA(Software component analysis,软件成分分析):如字面意思,此工具就是用来分析软件成分的,何为软件成分?那就先引入一个新的名词:SBOM[1](Software Bill of Materials,软件物料清单) 其概念来自于制造业,譬如汽车制造商为每辆汽车维护的BOM就列出了原始设备制造商和第三方供应商的零件清单,用于在发现零件缺陷的时候可以根据批次信息来跟踪处理。而在软件上,BOM描述的是软件包依赖树的一系列元数据,包括组件名称、版本号、许可证、版权等多项关键信息。目的是为了发现潜在的安全问题(软件漏洞)和许可证问题(假如你引用的开源软件用的是GPL许可证,那么你开发的软件也必须公开全部源代码,可以参考这个案例)。

SBOM的两大作用:

  1. 维护了一份软件的资产清单,在处理组件漏洞的时候可以快速定位到受影响的软件资产,避免了两眼一抹黑,连自家有哪些软件受漏洞影响都不知道的情况。
  2. 在DevSecOps的流程中嵌入SCA(软件成分分析)工具,通过对生成的SBOM进行漏洞和许可证匹配,在软件上线之前就检测出安全问题和许可证问题,可以减少上线后才发现问题而带来的很多麻烦。

一份完整的SBOM生产流程如下图所示[1],注意SBOM需要跟随软件的迭代而更新,因此需要使用自动化工具来创建,而SCA提供了这样的能力。

SBOM生产流程

既然已经有了SBOM,那就剩下用漏洞库去匹配这个清单,找出其中有漏洞的组件。公开的漏洞库包括有:NVD/CNVD/CNNVD,但这些国家级漏洞库收录的漏洞数量非常多,并且很多都是很陈旧的,越庞大的漏洞库虽然能带来越高的漏洞发现率,但也意味着匹配的时间越长。并且一个项目是否通过检查出来的漏洞数量来衡量其安全水位呢,也值得你去思考。我更推荐snyk vulnerability db,漏洞的数据格式一致,不需要用多个不同的html解析模板,并且数据的速度也够快,但使用爬虫去高频爬取这个漏洞库可能会存在法律风险。

下面介绍一下SCA里的一个知名开源产品:OWASP Dependency-Check,它的工作原理如下:

  1. 收集项目依赖信息:JarAnalyzer模块从Java项目的 Manifest, pom.xml 和 JAR 文件里的包名收集足够的项目依赖信息。
  2. 分析并索引漏洞库:将NVD的漏洞库解析出来并通过Lucene索引存储
  3. 匹配依赖与漏洞库:CPEAnalyzer模块会匹配项目中的每个依赖与漏洞库,最后将所有命中的漏洞库生成一个报告,报告内容如下[12]

漏洞报告

注意,OWASP Dependency-Check 并没有收集详细的SBOM,也没有致力于解决许可证风险,并不是SCA的完全体。而另一个开源项目 墨菲安全 - murphysec 则收集了SBOM并列举了许可证风险,可以参考一下。

ASOC

大家看到安全编排这个词时可能先想起的是 SOAR(Security Orchestration, Automation and Response,安全编排自动化与响应),但我在此文里强调的更多是应用安全,SOAR的概念要比 ASOC(Application Security Orchestration and Correlation,应用安全编排和关联)庞大且复杂。为了始终聚焦 DevSecOps ,我在此采用的是 ASOC 这个概念, synopsys 是这样来定义这个概念的:

应用安全编排和关联(Application Security Orchestration and Correlation,ASOC)是一种通过自动化的工作流来帮助简化漏洞测试和修复过程的应用安全解决方案,ASOC从各种应用安全工具(如SAST,DAST和IAST)收集数据并将他们合并到一个数据库中,然后通过关联分析这些数据来确定漏洞修复工作的优先级,最终使安全团队能够以知情且高效的方式来精简应用安全的运营工作。

从定义中就可以看到关键词:工作流,大家在日常工作中通过OA里发起的各种审批流程就是一个工作流:发起申请 -> 工作流创建并开始;各级人员审批 -> 工作流执行;流程归档 -> 工作流结束。因此 ASOC 工具的关键就是创建工作流,在不同的人员中自动化流转漏洞处理工单

对应的商业软件有 synopsys Code Dx ,但并没从中找到什么参考价值。反而可以从 工作流引擎原理-打造一款适合自己的工作流引擎 这篇文章里找到工作流的实现方法,下图展示了我们自己设计的漏洞工单工作流,在漏洞的修复流程中主要关联了开发人员和安全人员,在一个漏洞被修复的过程中,整个工单经过的流程如下所示:
漏洞工作流

我们所有的漏洞测试系统都关联到这个工作流中,当某个系统检测出了漏洞之后会自动创建工作流的实例并自动在企业微信上通知相关人员修复漏洞,当工单负责人修复好了漏洞之后,在我们的安全平台上点击“确定修复”之后,系统就会自动测试该漏洞是否真的已经被修复,只要复测通过就自动结束该流程,关闭工单。从整个流程可以看到,基本不需要安全人员介入,极大地节省了人力。

产品与工具矩阵图

下面罗列一下各种工具对应的开源和商业产品,有兴趣的可以挑出几个来分析。

SAST DAST IAST RASP SCA
开源 NodeJsScan, SonarQube, OWASP ZAP 洞态 IAST , baidu openrasp-iast, Shadowd OWASP AppSensor, 百度 openRASP 墨菲安全, OWASP Dependency-Check
商业 SonarQube, Synk, CheckMarx, Bandit, GitLeaks, Synopsys Acunetix, Synopsys, AppSpider, Acunetix, Burp Suite, Checkmarx 灵脉IAST 云鲨RASP, Contrast Security, Waratek Blackduck, DepScan, HCL AppScan, Synk, Sonatype, Synopsys

我的建设思路

结合我司的安全建设历程和效果,我认为整个工具链可以按照以下顺序来建设:

  1. SCA:软件成分分析应该摆在第一位,原因有以下几点:
    • 现在爆发严重漏洞的次数有越来越多的趋势,并且每个都很致命。在我司建设SCA之前,遇到这种情况就只能发整改表,依赖于业务自查;一方面会导致沟通成本非常高,另一方面,有些项目在交接过很多次之后就被人遗忘了,无法做到一个全局的掌握。将SCA嵌入到DevOps的流程中,在项目上线前先进行软件成分分析,从而掌握线上生产项目的资产表。如果不这样做,而是对公司的整个代码仓库进行软件成分分析,这样是没有意义的,因为我们并不关注那些没有在生产环境运行的项目代码。
    • SCA可以做到高度自动化,如果没有漏洞编排工具,那么将SCA系统与公司的IM软件(如企业微信,钉钉等)和告警系统打通也能实现一定程度上的漏洞编排功能。SCA并不仅仅是漏洞应急工具,更应该是一个日常运行的工具,毕竟随时会有开发人员无意间使用含有漏洞的第三方库。
  2. ASOC:安全编排工具可以与SCA进行同步开发,因为ASOC可以赋予SCA高度自动化的能力,并且在SCA上线前优化用户体验的时候也需要同步调整ASOC。有了ASOC之后,所有的安全服务都可以编排出来并按照流程自动化运行,彻底走出了手工excel运营的阶段。
  3. 制品扫描:曾经发生过的 XcodeGhost 风波是攻击者在非官方的 Xcode 软件中植入了后门从而将恶意代码植入到开发者生成的iOS应用程序中,属于供应链攻击的一种。所以即使代码经过了SCA的测试,最终生成的制品仍然可能是不安全的。最好的办法就是对生成的二进制程序或docker镜像再进行一次扫描,可以检查出这些SCA无法发现的问题:安全配置问题,编译选项检查,敏感信息检查等。
  4. 漏洞扫描器:安全团队一般都用来做日常的定期巡检,其实也可以对业务/SRE团队开放特定的扫描能力,用于在业务上线前进行web安全测试。
  5. SAST:我之前用过SonarQube来做静态代码扫描,但代码质量这个东西不好推广,因为每个项目都能检出一大堆问题,并且误报还不少,所以在试用过之后也搁置了。
  6. RASP:正如前文所说,RASP比较难推广,越是重要的公司级业务就越追求性能表现,现在为了加强安全而消耗掉部份性能,对业务来说是很难接受的;另一方面,万一RASP引入了新的故障点,这个也会严重破坏安全与业务人员和SRE之间的团队关系。但是RASP的确带来了很多新的优势,尤其是可以防那些未披露的漏洞,该技术可以保持长久的关注
  7. Fuzzing(模糊测试):这里引入的模糊测试在常规的DevOps流程中并不常见,在此做一下简单介绍:模糊测试是通过自动生成随机的数据值或文件去测试API,用于解决数据验证中的问题,并查看当传递了错误的值时系统会发生什么情况。安全研究人员通常使用Fuzzing技术来查找代码中的漏洞,但Fuzzing存在一个大的问题是在测试中可能使得系统崩溃,并且并不总是能提供很明确的错误反馈,需要人员投入大量的时间进行排查,因此该技术在自动化测试的流程中并不常见。

本文引用

[1] 软件供应链安全白皮书2021 by 悬镜
[2] RASP安全技术
[3] Java 动态调试技术原理及实践
[4] Apache Log4j2,RASP防御优势及原理
[5] Differences Between SAST, DAST, IAST, And RASP
[6] How Instrumentation-based IAST and RASP Revolutionize Vulnerability Assessment for Application
[7] Application Security Orchestration and Correlation
[8] 重磅推荐: 全球唯一开源的 IAST 自动化漏洞检测工具
[9] 《Google系统架构解密:构建安全可靠的系统》 希瑟·阿德金斯, 贝齐·拜尔, 保罗·布兰肯希普, 彼得·莱万多夫斯基, 阿那·奥普雷亚, 亚当·斯塔布菲尔德 著;周雨阳 刘志颖 译
[10]《敏捷应用程序安全》 Laura Bell, Michael Brunton-Spall, Rich Smith, Jim Bird 著;杨宏焱, 刘恒屹 译
[11]《DevSecOps敏捷安全》 子芽 著
[12] owasp扫描依赖漏洞笔记
[13] 工作流引擎原理-打造一款适合自己的工作流引擎

文章作者: kylinlin
文章链接: https://kylinlingh.github.io/2022/06/21/%E4%BC%81%E4%B8%9ADevSecOps%E6%B5%81%E7%A8%8B%E5%BB%BA%E8%AE%BE%E4%B9%8B%E5%B7%A5%E5%85%B7%E7%AF%87/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Water&Melon's Blog