「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等12个知识域的一百多个知识点,持续更新。
这一章节我们需要知道安全的软件开发模型有哪些,以及实现安全开发的具体支撑技术。
软件产品如果「运行不稳定」,会影响「可用性」;如果存在「漏洞」,被攻击利用,则会导致数据泄露或破坏,影响「完整性」和「机密性」。网络安全的三大支柱CIA,都能被软件安全影响,所以软件的安全问题是很严重的,必须要解决。
以往人们的解决方式,是等软件开发完成后,在「上线前做测试」,检测是否有安全问题,但这个时候做整改,「成本」会很高,想要降低成本,就需要把安全问题消灭在「软件开发过程」中,也就是业内常说的「安全左移」,或者叫「安全前置」。
软件开发安全
1、软件开发生命周期
想要实现「安全左移」,我们需要先了解软件开发的过程,开发过程也叫「生命周期」,常见的软件开发周期有以下几种:
- 「瀑布模型」:最早出现的模型,按照需求分析→功能设计→编码调试→安全测试→运行维护的顺序执行,向瀑布一样,执行完一步再执行下一步,如果某一步执行不下去,就回退到上一步。适合需求明确的场景。
- 「迭代模型」:在瀑布模型的基础上,多次迭代,每一次迭代都包含瀑布模型的所有流程。新的需求放到下一次迭代中实现。所有迭代都完成后,再交付。
- 「增量模型」:本质上是迭代,但每次迭代都会交付一个产品。
- 「快速原型模型」:增量模型的另一种形式,先做一个demo给用户去用,等用户反馈需求再开发。适合需求不明确的场景。
- 「螺旋模型」:在快速原型的基础上,在每次迭代过程中都增加风险分析的步骤,来降低开发的风险。
- 「净世模型」:严格把控过程,做到开发零缺陷。成本很高,适合不计成本的高精尖产业。
2、安全的软件开发生命周期
「安全问题越早解决成本越低」,根据NIST的统计:同一个安全问题,软件发布后修复和编码阶段修复比,成本要高30倍。这也是安全左移的原因。
安全问题「无法完全杜绝」,只能减少,为了减少安全问题,需要在软件开发生命周期的「各个阶段」采取相应的安全措施,也就是安全的软件开发生命周期,常见的有:SDL、CLASP、CMMI、SAMM、BSIMM。
2.1、SDL
SDL(Security Development Lifecycle)是微软提出的软件安全开发周期,分成七个阶段和十七个安全活动,每个阶段必须实现对应的安全活动。
培训阶段:
- 核心安全培训:强制对员工进行安全培训,比如开发人员学安全开发、测试人员学安全测试、需求分析人员学恶意建模等。
要求阶段:
- 确认安全要求:比如要不要过等保三级。
- 质量门/Bug栏:建立漏洞标准,哪种漏洞必须解决,哪种漏洞不用解决。
- 安全与隐私:检查软件会不会收集用户信息,符不符合数据安全法等相关法规。
设计阶段:
- 确认设计要求:比如架构设计、职责分配、功能设计、最小权限原则等。
- 分析攻击面:攻击面就是未经授权就能访问的入口,攻击面越小就越安全。
- 威胁建模:识别漏洞并采取防御措施。
实施阶段:
- 使用批准的工具:必须使用公司提供的工具开发,不能自己从网上下载,以防止工具中存在后门。
- 弃用不安全的函数:字面意思。
- 静态分析:不运行程序,分析源代码,也就是代码审计。
验证阶段:
- 动态分析:运行程序,发现存在的漏洞。
- 模糊测试:也就是Fuzzing,通过非预期的输入观察是否有异常的结果,来挖漏洞。
- 攻击面分析:再分析一次攻击面。
发布阶段:
- 事件应急计划:就是出现漏洞后应该怎么办。
- 最终安全评析:检查安全问题的解决情况,没解决的能不能接受,能接受就记录下来等下次发布的时候修改;不能接受的项目就不允许发布。
- 发布存档:对生命周期的相关资料记录存档,用于软件发布后的维护。
相应阶段:
- 执行应急事件计划:成立应急响应中心,接受白帽子、黑客、社区等各种途径的漏洞信息,分析确认并修复。
SDL流程很完善,适合大公司大团队使用。小公司人少,流程太复杂反而会降低开发效率,可以使用CLASP这种轻量级的安全开发周期。
2.2、CLASP
CLASP(Comprehensive Lightweight ApplicationSecurity Process)是OWASP推广的综合的轻量级应用安全过程,基于角色安排活动。
CLASP将角色分为:项目经理、需求分析师、软件架构师、设计者、实施人员、集成和编译人员、测试者、测试分析工程师、安全审计员。
每个角色分配对应的活动,并且描述每个活动需要多少成本,怎么实施,在什么时间执行,不执行会有什么风险。
判断自己的团队适合SDL还是CLASP,可以按照CMMI的等级,推荐团队通过CMMI3级再使用SDL。
3.3、CMMI
CMMI(Capability Maturity Model Integration)是软件能力成熟度模型集成,从低到高分为5个级别:
- CMMI1级:完成级,完成项目具有偶然性,不能保证实施同类项目仍然能够完成。
- CMMI2级:管理级,项目有一系列管理程序,避免了偶然性,能保证同类项目实施的成功率。
- CMMI3级:定义级,将管理程序制度化,不止同类项目,其他项目也能保证成功率。
- CMMI4级:量化级,将管理制度数字化,管理精细、流程稳定,项目质量波动小。
- CMMI5级:优化级,利用新技术主动改善、优化管理制度,预防次品。
CMMI有单独的评审机构,可以持续改进,提升等级。
3.4、SAMM
SAMM(Software Assurance Maturity Model)是OWASP提出的软件保证成熟度模型,分成5个阶段和15个安全活动,这个有点类似SDL。然后根据每个安全活动的评分高低,评价出0~3级,4个成熟度等级。
SAMM是一个开放的框架,对安全知识要求比较低。
3.5、BSI
BSI(Building Security IN)叫BSI系列模型,强调安全重点,注重实用方法,容易上手。
BSI提出软件安全由三大支柱构成,分别是应用风险管理、接触点、知识。
- 应用风险管理(Risk Management):是一种思想,也就是战略方法。
- 接触点(Touchpoints):是战术,具体的安全控制措施,也是是模型的核心。
- 知识(Knowledge):是知识库,用来安全培训,提高员工安全能力。
BSI根据软件安全所具有的行为,将接触点分为7种控制措施,并将7种控制措施在适当的实际插入软件开发生命周期。
- 代码审核:也就是源代码测试,扫描代码的漏洞。
- 风险分析:评估软件风险,并作对应的控制。
- 渗透测试:公司的红队定期渗透,发现并修复漏洞。
- 基于风险的安全测试:评估业务的安全,比如这个漏洞会关联到哪些业务,造成什么影响。
- 滥用案例:分析软件出现过的安全时间,分析并制定解决方案。
- 安全需求:比如软件要不要过等保三级。
- 安全操作:也就是安全运维,软件上线以后做安全加固、打补丁、修复漏洞等。
3.6、BSIMM
BSIMM(Building Security IN Maturity Mode)BSI成熟度模型,跟BSI没有直接关系,只是名字像。核心是根据其他公司的安全项目过程,来指导自己的安全项目。
它会将项目的安全性用雷达图来展示出来,我们可以看到哪个地方做的比较好,哪个地方做的不好。起到一个参考作用,不强制实践。
3、生命周期的安全活动
安全的软件开发生命周期想要落地,必须依赖具体的「安全活动」,接下来讲解一些必要的安全活动。这些安全活动在不同的安全模型中叫法可能不一样,但可以共用。
3.1、安全需求分析
安全需求分为「功能需求」和「保障需求」两类:
- 「安全功能需求」:就是软件为了安全需要实现哪些功能,比如标识鉴别、访问控制、审计、加密等功能。
- 「安全保障需求」:指实现安全功能的方法和手段, 比如威胁建模、安全设计、安全编程、代码测试、漏洞管理等手段。
安全需求分析时,需要从攻击者的角度出发,不仅考虑软件「需要实现什么」,还要考虑软件「不能实现什么」。
安全需求分析的执行过程如下:
- 系统调查。
- 分析系统的脆弱点和可能遭受的威胁。
- 定量分析脆弱点和安全威胁。
- 确定安全需求。
3.2、软件安全设计
软件安全设计分为概要设计和详细设计两个阶段:
- 软件安全概要设计:大的框架,比如架构设计、功能之间的关系。
- 软件安全详细设计:编码功能的细节,比如每个功能模块使用什么数据结构、算法,功能的具体逻辑、处理流程。
安全设计原则:
- 「最小特权原则」:能给普通用户就不给系统用户,能给只读就不给修改。
- 「权限分离原则」:比如等保中的三权分立,用系统管理员、安全管理员、审计管理员替代超级管理员。
- 「最少共享机制原则」:比如克隆一个生产环境给某个员工测试,而不是直接给员工生产环境的访问权限。
- 「完全中立原则」:比如没有直接利益的、权威的第三方机构。
- 「心理可接受原则」:安全和用户体验往往是两个相反的方向,我们需要在两者之间寻求平衡。
- 「默认故障处理保护原则」:报错时用特定的内容,代替程序原本的报错内容,防止报错注入或信息泄露这种威胁。
- 「经济机制原则」:安全成本要适度。比如一个数据价值一万,你用十万做安全防护,就得不偿失了。
- 「不信任原则」:假设所有的输入都是恶意的,比如:对用户的输入做严格过滤,防止SQL注入这类攻击;用户输入密码错误5次就冻结30分钟。
- 「纵深防御原则」:设置多层重叠的安全防护,即使某一防线失效也能被其他防线弥补或纠正。
- 「保护最薄弱环节原则」:比如Web、邮件这种最容易遭受攻击的地方,需要重点防护。
- 「公开设计原则」:假设所有技术细节都被公开了,也不会影响系统的安全。
- 「隐私保护原则」:收集用户信息等操作,必须符合相关法规。
- 「攻击面最小化原则」:能被访问的入口越少,系统就越安全。
3.3、降低攻击面
所有能访问系统的入口都是攻击面,攻击面越小就越安全。
分析攻击面主要有三个思路:
- 「功能重要性」:不重要的功能直接关闭;重要的功能加强防护。
- 「访问方式」:远程访问>受限访问>本地访问。能本地就不受限,能受限就不远程。
- 「访问权限」:匿名访问>用户访问>仅管理员访问。
降低攻击面实例:
比如:只允许特定的IP访问服务器。
3.4、威胁建模
威胁建模是了解威胁、确定威胁风险、缓解风险,从而提高系统安全性的一个过程。
扩展:威胁永远存在,威胁不等于漏洞,漏洞是威胁的一种体现形式。
威胁建模有4个流程:
- 确定对象:小到一个API接口,大到一个OS,都是可能存在威胁的对象。
- 识别威胁:识别微软定义的STRIDE六种威胁。
- 评估威胁:评估威胁的影响,确定哪些威胁需要处置,哪些不需要处置。
- 消减威胁:采取对应的措施缓解风险。
微软制定了STRIDE威胁模型,也就是六种威胁类型首字母缩写,威胁详情和对应的缓解措施见下图:
威胁类型 | 安全属性 | 缓解措施 |
---|---|---|
Spoolfing identity(假冒身份) | 认证 | 双因子/多因子认证、数字证书、PKI、Kerberos认证等认证方式。 |
Tampering with data(篡改数据) | 完整性 | 哈希算法、消息鉴别码MAC |
Repudiation(抵赖) | 抗抵赖 | 数字签名、安全审计、时间戳 |
Information disclosure(信息泄露) | 机密性 | 加密、访问控制、隐私保护 |
Denial of service(拒绝服务) | 可用性 | 备份、设备冗余、链路冗余 |
Elevation of privilege(提权) | 授权 | 访问控制列表、最小权限运行 |
3.5、安全编码
- 验证输入:对所有的输入,先检查、验证、过滤,再参与业务逻辑。防止SQL注入这种攻击。
- 验证内部接口:外部的输入不可信,内部的输入同样不可信,程序内部接口的数据,也要检查可靠性、完整性。
- 避免缓冲区溢出:动态分配内存、控制输入的大小、使用没有缓冲区溢出问题的函数或库。
- 处理异常:用特定的内容替代程序的报错内容。
- 最小化反馈:比如登录功能只反馈成功或失败,而不是反馈用户名错误、用户未注册。
- 避免条件竞争:使用原子操作或加锁。
- 临时文件及时清空。
- 开源框架要检查是否有漏洞,检查是否使用了不安全的函数。
- 系统命令调用函数,比如system等函数调用外部命令时,要过滤参数。
- 返回值检查是否成功,如果成功就检查返回值内容、类型是否符合预期;不成功要检查、处理后在返回。
- 程序组件之间的数据传输,尽可能加密,加密要用安全的算法和协议。
- 检查是否使用危险函数。
3.6、安全编译
编译环境使用可靠的编译工具,用公司提供的工具而不是自己从网上下载,工具要用最新版,使用前检查开启编译器内部的防御特性。
运行环境要用较新版本的系统,越老的系统往往漏洞越多。
3.7、代码审计
使用静态分析的方式,分析程序源代码中的语法、结构、逻辑、接口等,检查程序中存在的错误或缺陷。
先用工具审核,然后人工审核是否有误报。
3.8、安全测试
通过动态分析的方式,检查程序运行过程中,功能、性能、安全性是否符合要求。
传统的软件测试主要有以下方式:
- 单元测试:测试范围是模块,给软件的某个模块做测试。
- 集成测试:测试范围是软件,给软件整体做测试。
- 系统测试:测试范围是系统,软件、网络、数据库等联合起来,系统的做测试。
- 黑盒测试:软件内部完全不清楚的情况下做测试,也就是黑客的角度。
- 白盒测试:软件内部完全清晰的情况下做测试,能拿到软件的源码等所有信息。
- 灰盒测试:软件内部部分清晰的情况下做测试,能拿到架构图、功能逻辑图等部分信息。
- 静态测试:不运行软件,做测试。
- 动态测试:运行软件,做测试。
- 代码走查:研发组内部自发性检查测试。
- 代码审查:研发组正式检测,输出计划、流程、结果报告。
- 代码评审:研发组、测试组等多个部门联合测试。
- 回归测试:某次测试完成后,测试问题的修复效果。只测问题本身,不做全面测试。
- 验收测试:项目结项前的测试。
传统测试只考虑软件出错时如何处理,不考虑软件不出错时的故意攻击。
安全测试则重点检查软件的安全特性。比如等保中提出的安全特性就包括:身份鉴别、访问控制、安全审计、入侵防范、恶意代码防范、可信验证、数据完整性、数据保密性、数据备份恢复、剩余信息保护、个人信息保护。
安全测试分功能性、对抗性两种:
- 功能性安全测试:检查软件的安全功能是否实现,比如等保测评。
- 对抗性安全测试:使用黑客的角度测试,比如渗透测试。
安全测试方式主要有模糊测试、渗透测试、代码审计三种:
- 模糊测试:也叫Fuzzing测试,通过非预期的输入,检查软件执行结果,是目前主流的挖洞方法。
- 渗透测试:从黑客的角度来攻击,发现漏洞。需要授权且不具备破坏性。
- 代码审计
3.9、安全交付
- 供应链安全:通过官方等正规渠道,获取可靠的框架、三方库、编译软件等。
- 软件验收:软件的安全性要纳入验收的标准中。
- 安全部署:提供部署文档和工具,部署后对软件进行安全配置和加固。