# 一、软件安全开发概述
# 1. 软件生命周期
开发阶段:安全需求分析 → 安全设计 → 安全编码 → 安全测试 → 安全交付 五个核心环节
安全贯穿性:安全措施需要贯穿信息系统开发的 整个生命周期,而非仅在后期补充。
# 2. 软件危机(三次危机)
| 阶段 | 时间 | 根源 | 解决方案 |
|---|---|---|---|
| 第一次危机 | 1960s | 汇编语言难以应对复杂程序开发 | 采用软件工程的 分模块开发 模式 |
| 第二次危机 | 1980s | 软件规模突破 百万行代码 量级 | 面向对象语言(C++/Java/C#) |
| 第三次危机 | 2000s | 软件安全问题凸显 | SDL(安全开发生命周期)管理 |
语言趋势:Python 因易学易用逐渐取代 Java,但底层开发仍需 C 语言。
# 3. 软件安全问题产生
# 内因
- 代码规模效应:功能复杂度与代码量正相关,SLOC(百万行代码)增长导致漏洞密度上升
- 模块复用风险:复用模块可能继承原有安全缺陷;扩展模块引入新的攻击面
- 典型案例:Windows 操作系统版本迭代中代码量持续增加
# 外因
- 环境因素:互联网技术发展提升攻击者能力;市场优先考虑交付周期和功能完整性
- 人为因素:开发者安全知识缺乏(如使用危险函数);需求分析不充分导致设计缺陷
- 工具链缺陷:安全开发工具支持不足;配套管理 / 测试工具缺失
# 4. 软件安全保障
核心原则:
- 通过全生命周期措施 减少(非杜绝)漏洞
- 安全能力需与威胁水平相适应
各阶段控制:
| 阶段 | 控制要点 |
|---|---|
| 需求阶段 | 明确安全需求基线 |
| 设计阶段 | 遵循安全设计准则 |
| 编码阶段 | 执行安全编码规范 |
| 测试阶段 | 验证安全控制有效性 |
| 运维阶段 | 持续监控漏洞状态 |
# 二、软件开发生命周期模型
# 1. 瀑布模型
- 特点:线性流程:系统需求→软件需求→设计→编码→测试→运维
- 缺陷处理:发现问题只能回退到 上一阶段(如测试问题仅能追溯至编码阶段)
- 典型缺陷:未规定后期发现重大错误时的处理机制
# 2. 迭代模型
- 改进点:在每个阶段加入 风险评估 环节
- 灵活调整:发现问题可回退多步重新设计
- 优势:降低增量开发风险,加快市场响应速度
# 3. 增量模型
- 现代应用:版本迭代(V1.0→V2.0 逐步完善功能)
- 敏捷开发:快速响应需求变更,典型如 APP 版本更新
- 特点:每个增量都是可独立运行的完整产品
- 安全挑战:模块复用导致漏洞延续
# 4. 螺旋模型
- 核心创新:风险驱动。每个阶段强制进行风险分析
- 终止机制:发现重大风险时可中止项目
- 优势:通过原型开发降低风险,减少后期修复成本
# 5. 净室模型
- 核心目标:零缺陷,通过数学统计方法逼近零缺陷
- 适用场景:航天等高可靠性系统开发
- 现实局限:实际开发中无法真正达到零缺陷
# 6. 模型对比总结
| 模型 | 核心特点 | 适用场景 | 局限性 |
|---|---|---|---|
| 瀑布模型 | 线性单向流程 | 需求明确的小型项目 | 后期发现问题难回溯 |
| 迭代模型 | 分阶段 + 风险评估 | 中等规模项目 | 需较强项目管理能力 |
| 增量模型 | 版本迭代、敏捷 | APP 开发、快速上线 | 模块复用引入安全风险 |
| 螺旋模型 | 风险驱动、可终止 | 高风险大型项目 | 流程复杂、成本高 |
| 净室模型 | 数学统计、零缺陷 | 航天 / 高可靠性系统 | 实际无法达到真正零缺陷 |
# 三、软件缺陷与漏洞
# 1. Bug 与漏洞的区别
| 维度 | Bug | 漏洞 |
|---|---|---|
| 本质 | 功能性问题(功能异常 / 界面卡顿) | 安全性问题(可被利用) |
| 用户感知 | "软件不好用" | 无明显感知,但存在风险 |
| 举例 | 按钮无响应、页面白屏 | 远程执行漏洞、提权漏洞 |
转化关系:
- 部分 Bug 可能演变为漏洞(如功能缺陷导致安全边界突破)
- 存在 独立漏洞:软件运行稳定但仍存在可被利用的安全缺陷
行业术语:安全领域统一称 "漏洞",强调可被利用性。不可利用的漏洞视为残余风险或低危漏洞。
# 2. 千行代码缺陷密度标准
CMMI 分级标准:
| CMMI 等级 | 缺陷率(缺陷 / 千行代码) | 特征 |
|---|---|---|
| CMMI 1 级(初始级) | 11.95‰ | 无序过程 |
| CMMI 2 级(管理级) | 5.52‰ | 可重复过程 |
| CMMI 3 级(定义级) | 2.39‰ | 标准化过程 |
| CMMI 4 级(定量管理级) | 0.92‰ | 可预测过程 |
| CMMI 5 级(优化级) | 0.32‰ | 持续改进 |
行业基准:
- 普通软件公司:4-40 个缺陷 / 千行代码
- 高管理软件公司:0-4 个缺陷 / 千行代码
- 美国 NASA 航天级:0-0.1 个缺陷 / 千行代码
# 3. 漏洞库体系
| 漏洞库 | 全称 | 特点 |
|---|---|---|
| CNVD | 国家漏洞共享平台 | 含补丁信息 |
| CNNVD | 国家漏洞库 | 官方披露平台 |
近年峰值:年收录漏洞 7000+ 个
# 四、软件安全开发生命周期模型
修复成本规律:软件安全问题越早解决成本越低,发布后修复代价是设计 / 编码阶段的 30 倍(NIST 数据)。
# 1. SDL 模型(Microsoft)
发展历程:2002 年微软比尔・盖茨发起 → SDL 1.0 到 5.2 多个版本迭代
典型案例:Windows Vista 是首个采用 SDL 开发的操作系统
7 阶段划分(5+2):
| 阶段 | 关键活动 |
|---|---|
| ① 培训 | 核心安全培训(首要环节) |
| ② 要求 | 安全需求确定、风险评估 |
| ③ 设计 | 威胁建模、攻击面分析 |
| ④ 实施 | 使用安全工具、弃用危险函数 |
| ⑤ 验证 | 模糊测试、动态分析 |
| ⑥ 发布 | 最终安全评析、存档 |
| ⑦ 响应 | 漏洞事件处理 |
成效数据:
- IE 漏洞总数下降 35%,高危漏洞下降 63%
- 操作系统漏洞总数降低 45%
# 2. CLASP 模型
- 定位:综合的轻量应用安全过程(Comprehensive, Lightweight Application Security Process)
- 核心机制:基于 30 项特定活动 的角色安全分配,提供角色对应的安全指南和检查列表
- 适用场景:适合 小型企业 开发团队
# 3. CMMI 模型
五级成熟度体系:
| 等级 | 名称 | 特征 |
|---|---|---|
| ML1 | 初始级 | 无序过程 |
| ML2 | 管理级 | 可重复过程 |
| ML3 | 定义级 | 标准化过程 |
| ML4 | 定量管理级 | 可预测过程 |
| ML5 | 优化级 | 持续改进 |
应用价值:高级别认证可承接国家重点研发项目。
# 4. SAMM 模型
框架特点:开放的 四模块框架(治理、构造、验证、部署),安全知识要求门槛较低
| 模块 | 活动 |
|---|---|
| 治理 | 策略与遵循、培训 |
| 构造 | 安全需求、架构设计 |
| 验证 | 代码审查、安全测试 |
| 部署 | 漏洞管理、环境加固 |
# 5. BSI / BSIMM 模型
核心支柱:
- 风险管理:全生命周期风险策略
- 接触点:对命令行、网络等所有交互入口的安全检测
- 安全知识:开发人员安全培训体系
工作方式:
- 本质是 行业最佳实践参考指南(非强制性)
- 对 42 项安全活动 进行量化
- 分类汇总各类安全标准
# 6. 五大模型对比
| 模型 | 核心优势 | 适用企业 | 特点 |
|---|---|---|---|
| SDL | 文档工具完善、微软维护更新 | 大型企业 | 7 阶段 17 项活动 |
| CLASP | 轻量级、角色驱动 | 小型团队 | 30 项安全活动 |
| CMMI | 五级成熟度、持续改进 | 各类规模 | 支持评估认证 |
| SAMM | 开放框架易对接、知识门槛低 | 中大型企业 | 四模块框架 |
| BSI/BSIMM | 行业实践集合、三支柱方法论 | 参考导向 | 非强制、42 项活动 |
# 五、软件安全需求及设计
# 1. 安全需求分析
基础性作用:安全需求和设计是开发安全软件的基础,若需求和设计阶段存在安全问题,后期修复代价特别大。
因果关系:先有安全需求设计才能实现安全开发,后期开发出的软件安全性直接取决于前期设计。
风险管理方法:
- 以 风险管理 角度建立威胁分析计划
- 定性分析 + 定量分析 相结合
- 网络安全本质就是风险管理
需求文档化必要性:
- 避免甲方口头需求不明确
- 防止需求描述模糊
- 便于与客户确认具体实现效果
- 变更流程:说明变更原因 → 评估变更影响
# 2. 安全需求分类
| 类型 | 说明 | 示例 |
|---|---|---|
| 功能需求 | 软件功能本身的安全性 | 上传下载功能的安全实现 |
| 保障需求 | 符合标准法规要求 | CMMI 级别、等保、网络安全法 |
需求分析要点:
- 既要定义系统 应该做什么,也要定义系统 不应该做什么
- 功能、安全需求与安全目标的 平衡
- 从 用户角度 考虑功能,从 攻击者角度 考虑漏洞
# 3. 安全设计原则(13 项核心原则)
数据支撑:50% 的安全问题由 设计瑕疵 引起(Gary McGraw 研究)
# ① 最小特权原则(Least Privilege)
- 定义:用户只能获得执行工作必需的 最小权限
- 违规示例:人力部门员工可跨部门访问所有数据
- 类比:类似超级管理员权限过大属于违规
# ② 权限分离原则(Separation of Duties)
- 核心要求:关键操作需 ≥2 人授权 才能执行
- 防护目的:防止单人权限过大导致数据泄露
- 系统实现:双因素身份认证登录机制
# ③ 审计与安全分离原则
- 禁止行为:同一人兼任网络管理员、系统管理员、安全责任人和审计员
- 类比:不能既当球员又当裁判
- 法律依据:网络安全法要求关键基础设施必须设立独立安全团队
- 账号管理:禁止账号共用,确保操作可追溯
# ④ 强制休假与轮岗制
- 强制休假:带薪长假期间由他人接替工作(变相审计手段,非心理健康关怀)
- 轮岗制:确保业务连续性,性质与强制休假不同
# ⑤ 最少共享机制原则(Least Common Mechanism)
- 正确做法:仅共享特定文件而非整个目录
- 风险:多个非涉密文件组合可能产生涉密信息
# ⑥ 默认故障处理保护原则(Fail-Safe Defaults / 默认拒绝)
- 典型表现:统一返回 "程序内部错误" 等模糊信息
- 防护目的:避免泄露系统细节给攻击者
# ⑦ 保护最薄弱环节原则(Protect Weakest Link)
- 关键对象:漏洞是最典型的薄弱环节
- 管理要求:必须建立完善的漏洞管理机制
- 木桶原理:系统安全程度取决于最薄弱的环节
# ⑧ 公开设计原则(Open Design)
- 采用 国际标准化方案 而非私有设计
- 标准化方案维护人员多、升级快、经受过安全检验
- 典型应用:加密算法应选用 AES 等国际标准而非自研算法
# ⑨ 纵深防御原则(Defense in Depth)
- 核心理念:多层防御,单点失效不影响整体
- 实施方式:网络层 + 主机层 + 应用层 + 数据层多层防护
- 类比:城堡不是只有一道城墙,而是护城河 + 城墙 + 内城多层防御
# ⑩ 完全中介原则(Complete Mediation)
- 定义:系统对每个访问请求都必须进行权限检查,不能遗漏
- 实施要求:每次访问都需验证,不能假设 "之前验证过就放行"
# ⑪ 经济机制原则(Economy of Mechanism)
- 定义:安全机制应尽量 简洁(Keep It Simple, Secure)
- 原因:复杂机制增加攻击面和实现错误的概率
- 类比:越简单的锁越难出故障,越复杂的锁越容易有设计缺陷
# ⑫ 最小信任原则(Least Trust)
- 定义:默认不信任任何模块、用户或输入
- 实施:所有输入必须验证,所有调用必须鉴权
# ⑬ 心理可接受性(Psychological Acceptability)
- 定义:安全机制应易于使用,否则用户会绕过
- 典型问题:密码复杂度要求过高→用户贴纸条在显示器上
# 4. 攻击面最小化
基本原则:攻击面越小,安全风险越小。
典型措施:
| 措施 | 说明 |
|---|---|
| 网络配置 | 关闭非必要网络连接,仅监听 TCP 流量 |
| 访问控制 | 实施强 ACL,禁止匿名访问 |
| 权限管理 | 代码以低权限账户运行 |
| 协议选择 | .NET 代码优于 ActiveX 控件 |
降低攻击面的策略:
| 功能重要性 | 处理方式 | 示例 |
|---|---|---|
| 🟢 低 | 直接取消 | 日均使用量 < 10 人的 FTP 服务 |
| 🟡 中 | 设为非默认开启 | 30-50 人使用的服务 |
| 🔴 高 | 增加安全限制 | 百人以上服务设置 IP 白名单 |
防护效果:完善的访问控制可预防 50%-60% 的安全问题。粗放的访问控制属于策略性漏洞。
# 5. 威胁建模
定义:威胁建模是通过识别系统面临的安全威胁,确定威胁风险并采取缓解措施来降低风险、提高系统安全性的过程。
价值:
- 在设计阶段全面识别安全威胁
- 指导选择适当应对措施
- 降低系统受攻击面
- 验证架构设计合理性
# 威胁建模四阶段流程
确定对象 → 识别威胁 → 评估威胁 → 消减威胁
① 确定对象:关键资产识别、使用场景分析、部署配置信息、用户行为模式
② 识别威胁:穷举所有可能威胁,关注威胁利用路径,分析威胁交互关系
③ 评估威胁:风险值 = 发生可能性 × 影响程度,需量化被利用概率和资产损失程度
④ 消减威胁:架构重新设计、标准消减技术、创新防护方法、记录暂未处理威胁
核心原则:必须处理每个识别到的威胁,根据 STRIDE 分类采取针对性措施,平衡防护成本与风险承受能力。
# STRIDE 六类威胁模型
| 类别 | 英文 | 含义 | 防护措施 |
|---|---|---|---|
| S - 欺骗 | Spoofing | 伪装身份(如仿冒网站) | 身份认证 |
| T - 篡改 | Tampering | 数据 / 代码修改(如篡改 DLL) | 完整性校验 |
| R - 抵赖 | Repudiation | 否认操作行为(如 "我没发过邮件") | 数字签名 |
| I - 信息泄露 | Information Disclosure | 未授权信息泄露 | 加密 |
| D - 拒绝服务 | Denial of Service | 服务不可用(如耗尽 CPU) | 冗余设计 |
| E - 权限提升 | Elevation of Privilege | 普通用户获管理员权限 | 权限管控 |
⚠️ 注意:六类威胁无直接可比性,不能简单判断某类更严重。访问控制可解决 50-60% 的安全问题,适用于多数威胁场景。
# 六、软件安全实现
# 1. 安全编码原则
# ① 输入验证
- 数据防火墙:对所有输入数据进行检查、验证及过滤
- 验证时机:最初接收数据时 + 第一次使用数据时(双重验证)
常见输入源验证要求:
| 输入源 | 验证要点 |
|---|---|
| 命令行 | 验证参数数量、数据格式及内容 |
| 环境变量 | 可能超出期望范围,存在危险存储格式 |
| 文件 | 不信任用户可控文件内容,临时文件需特别处理 |
| 网络 | 所有网络数据都应视为 "高度不可信" |
SQL 注入案例:
DROP DATABASE TABLE语句通过未经验证的输入执行,可删除整个数据库。
# ② 避免缓冲区溢出
溢出原理:当数据写入超过分配的内存空间时发生。
危险函数(C/C++):
| 危险函数 | 安全替代 |
|---|---|
strcpy | strncpy (限制拷贝长度) |
strcat | strncat (限制拼接长度) |
gets | fgets (指定最大读取长度) |
sprintf | snprintf (指定输出大小) |
防御措施:
| 技术 | 原理 |
|---|---|
| 动态分配内存 | 按需分配,避免固定大小的溢出 |
| StackGuard | 栈保护探测值(Canary) |
| 非执行堆栈 | 禁止在栈上执行代码 |
| ASLR | 地址空间布局随机化 |
典型案例:永恒之蓝漏洞(MS17-010)即由缓冲区溢出引起。
# ③ 程序内部安全
| 要点 | 实施方式 |
|---|---|
| 最小化反馈 | 前台仅显示 "程序错误",详细日志记录在后台 |
| 异常处理 | 检测所有可能运行路径,错误行为必须安全处理 |
| 竞争条件防范 | 使用原子操作、合理应用锁机制(避免死锁) |
# ④ 安全调用组件
- 调用检查:验证返回值是否成功、检查数据是否含 NUL 字符等异常
- 数据传输保护:根据安全需求加密、使用安全协议
- 依赖组件:操作系统、数据库、可重用库、网络服务(Web/DNS)
# 2. 代码安全编译
| 要点 | 建议 |
|---|---|
| 编译器选择 | 使用 最新版本,启用内置防御特性 |
| 运行环境 | 基于新版系统,使用可靠编译工具 |
| 安全风险 | 盗版编译器可能植入恶意代码 |
| 审计要求 | 编译过程需审计跟踪 |
# 3. 代码安全审核
审核目的:
- 识别潜在安全漏洞
- 验证安全控制措施有效性
审核方法对比:
| 方法 | 优势 | 劣势 |
|---|---|---|
| 人工审核(代码走查) | 精确、能发现逻辑漏洞 | 效率低,仅发现 30-70% 缺陷 |
| 工具审核(静态分析) | 基于知识库快速扫描(如 SonarQube) | 可能漏报逻辑类漏洞 |
区分:代码审计 = 安全导向,专门查找漏洞;代码审核 = 质量导向,检查语法 / 结构缺陷。
# 七、软件安全测试
# 1. 测试概念与信条
核心目的:通过人工或自动化手段检验系统是否满足需求,识别预期与实际结果的差异。
测试信条(黄金准则):
- 预先确定性:测试结果必须可预期
- 有效性:好的测试用例能高概率发现错误
- 独立性:测试应与编码分离,使用不同工具
- 专业要求:需同时具备用户视角和编程知识
# 2. 测试方法对比
| 方法 | 掌握信息 | 特点 | 示例 |
|---|---|---|---|
| 黑盒测试 | 仅输入输出接口 | 模拟用户视角 | 域名测试 |
| 白盒测试 | 完整内部结构 | 全面覆盖 | 流程图 / 拓扑图测试 |
| 灰盒测试 | 部分内部信息 | 混合模式 | 外部测试 + 已知内部结构 |
# 3. 模糊测试(Fuzz Testing)
- 核心机制:通过 畸形数据输入 监测系统异常
- 测试用例:随机生成大量非常规数据(如 SQL 注入 payload)
- 典型工具:AFL、Peach Fuzzer
- 有效性:能发现约 70% 的逻辑设计缺陷
# 4. 渗透测试
关键阶段:
授权获取 → 信息收集 → 漏洞利用 → 报告输出
| 阶段 | 说明 |
|---|---|
| ① 授权获取 | 必须 签订测试协议(未经授权渗透测试属于违法行为) |
| ② 信息收集 | 使用 nmap 等工具扫描 |
| ③ 漏洞利用 | 验证 SQL 注入 / XSS 等漏洞 |
| ④ 报告输出 | 注明风险等级和修复建议 |
时间选择:建议在业务低峰期(如夜间)执行。
# 5. 测试风险管理
- 数据备份:防止测试导致数据丢失
- 应急方案:制定系统恢复流程
- 法律边界:未经授权的渗透测试属于违法行为
# 八、软件安全交付
# 1. 软件供应链安全
全生命周期威胁:
| 环节 | 风险 | 典型案例 |
|---|---|---|
| 代码编写 | 共享库引入缓冲区溢出等漏洞 | OpenSSL 心脏滴血 |
| 代码编译 | 被污染的编译软件植入木马 | 编译器污染攻击 |
| 软件分发 | 非官方渠道下载含插件 / 流氓软件 | 2018 年百度下载站被劫持事件 |
| 软件更新 | 升级包被篡改或含防盗版机制 | 供应链投毒攻击 |
防护验证手段:
- 哈希校验:对比下载文件的哈希值与官网公布值
- 官方镜像站:推荐 MSDN I tell you 获取原版系统镜像
供应链安全策略:
| 维度 | 措施 |
|---|---|
| 代码管理 | 第三方代码审查、优先选用安全检测过的共享库 |
| 编译环境 | 可信编译器(官方渠道获取)、验证编译产物完整性 |
| 分发更新 | 官方渠道优先、企业自建内部软件分发站 |
# 2. 软件验收部署
验收流程:
- 监理全程参与项目周期(计划、需求、设计阶段)
- 制定正式验收流程
- 验证需求符合性
- 76 项标准验收条目
安全验收要点:
- 安全补丁检查
- 安全开发验证
- 部署文档完整性
# 3. 安全部署措施
| 措施 | 内容 |
|---|---|
| 软件加固 | 安全配置检查、攻击面分析、本地化运行策略 |
| 供应链安全 | 验证软件来源、第三方组件安全审计 |
| 文档配套 | 提供完整的部署文档和工具 |
# 附:知识小结(考试重点速查)
| 知识点 | 核心内容 | 难度 | 考试重点 |
|---|---|---|---|
| 软件危机 | 三次危机:汇编→面向对象→安全爆发 | ⭐⭐⭐ | 各阶段技术演进与核心矛盾 |
| 开发模型对比 | 瀑布 / 迭代 / 增量 / 螺旋 / 净室 | ⭐⭐⭐⭐ | 模型特点差异(瀑布仅回退一步 vs 螺旋全程风险分析) |
| Bug vs 漏洞 | Bug = 功能异常,漏洞 = 可被利用 | ⭐⭐ | 漏洞必是 Bug?→ 否 |
| 缺陷密度 | CMMI 五级:11.95‰→0.32‰ | ⭐⭐ | 各等级缺陷率对应关系 |
| SDL | 微软 7 阶段(培训→响应) | ⭐⭐⭐⭐ | 培训阶段的重要性 |
| CLASP | 30 项安全活动、角色驱动 | ⭐⭐ | 适用于小型团队 |
| CMMI | 五级成熟度(ML1-ML5) | ⭐⭐⭐ | 各级别特征 |
| SAMM | 四模块:治理 / 构造 / 验证 / 部署 | ⭐⭐ | 开放框架、知识门槛低 |
| 威胁建模 STRIDE | 六大威胁分类 | ⭐⭐⭐⭐ | 威胁≠漏洞(外部利用 vs 内部缺陷) |
| 安全设计原则 | 13 项核心原则 | ⭐⭐⭐ | 最小特权、纵深防御等原则的应用场景 |
| 攻击面最小化 | 关闭非必要功能、访问控制 | ⭐⭐⭐ | 风险消减策略(规避 / 转移 / 缓解 / 接受) |
| 缓冲区溢出 | strcpy 等危险函数→安全替代 | ⭐⭐⭐⭐⭐ | 防护措施(边界检查 / StackGuard/ASLR) |
| 安全编码 | 输入验证、双重验证机制 | ⭐⭐⭐⭐ | strcpy→strncpy 等安全替代 |
| 模糊测试 | 畸形数据输入测试 | ⭐⭐⭐⭐ | 发现约 70% 逻辑缺陷 |
| 渗透测试 | 授权→信息收集→利用→报告 | ⭐⭐⭐⭐ | 与黑客攻击的本质区别:合法授权 |
| 软件供应链安全 | 编写 / 编译 / 分发 / 更新 | ⭐⭐⭐⭐ | 正版编译器与镜像源的重要性 |
| 安全测试类型 | 黑盒 / 白盒 / 灰盒 | ⭐⭐⭐ | 功能性测试 vs 对抗性测试的区别 |
📝 备考建议:
- ★★★★★:缓冲区溢出(含危险函数替代)、STRIDE 六类威胁模型
- ★★★★:SDL 流程、安全编码原则、安全设计原则、渗透测试流程、供应链安全
- ★★★:开发模型对比、CMMI 等级、攻击面最小化、模糊测试
- ★★:缺陷密度标准、CLASP、软件危机历史