静态代码分析与代码质量安全
HeartBleed Bug
Heartbleed漏洞,这项严重缺陷(CVE-2014-0160)的产生是由于未能在memcpy()调用受害用户输入内容作为长度参数之前正确进行边界检查。攻击者可以追踪OpenSSL所分配的64KB缓存、将超出必要范围的字节信息复制到缓存当中再返回缓存内容,这样一来受害者的内存内容就会以每次64KB的速度进行泄露。
代码静态分析
• 定义:在不执行计算机程序的条件下,对源代码进行分析,找出代码
缺陷
• 执行方式:一般配合静态程序分析工具进行
• 采用技术:数据流分析、机器学习、语义精简…
• 可检测类型:死锁,空指针,资源泄露,缓冲区溢出,安全漏洞,竞态条件…
• 优点:
• 能够检测所有的代码级别的可执行路径组合,快速,准确
• 直接面向源码,分析多种问题
• 在研发阶段开始找到并修复多种问题,节省大量时间/人力成本
• 注意:静态分析不是万能的,测试是持续的过程,非一劳永逸
存在问题
• 编译器警告: 保证类型安全
– 最初级的静态分析,检测规则简单
• 中间语言分析: 检测字节码( Byte Code )的缺陷,将其重新映射到真实代码中
– 在转换与映射过程中易造成精度丢失
• 高误报率:目前静态分析产品的误报率普遍在30%以上。
• 缺陷种类较少,找到的问题级别不高:多数为代码规范或低级缺陷,非实际Bug
– 如命名规范、类定义规范,最佳实践…..
• 易用性较低:基本上都是一次性的使用工具,无法与SDLC集成
– SCM集成:如SVN,CVS,Perforce,Git
– Bug Tracking:如Bugzilla,Jira
改进型的静态分析方案
基于Meta Compilation的静态分析:
• 由斯坦福大学教授Dawson Engler提出,在深度理解代码与程序语义的基础上检测缺陷
• 旨在查找“真正的代码缺陷”
• 实现原理:
• 使用可扩展的metal语言定义正确性Checker
• 将程序的源码使用状态机进行抽象描述(State Machine Abstraction)。
• 使用xgcc系统匹配Checker与抽象状态机状态,找到问题所在的点。
• 可准确检测实际的Bug(内存和指针问题、资源泄露、缓冲区溢出,数组越界,
心脏出血漏洞…)
• 能够检测高达亿行级别的代码库,避免“状态爆炸”
• 使用模型检验与符号执行技术,误报率降低至15%以下
• 算法已步入实际应用
• 面向企业的Coverity 软件
• 面向开源代码的Coverity SCAN
如何进行Java代码静态分析?
Java语言被编译成JVM bytecode – 在运行时被转换成本地可执行
代码的分析
选项一
• 分析 byte-code:用户编译他们的软件,然后分析编译后的可执行文件与调试信息,分析引擎联系找到的缺陷与源代码位置
• 某些开源工具的实现原理
选项二:
• 获取所有的Java编译过程并执行分析
• Bytecode分析工作仍旧存在,但包含更多的内容
基本的工作流
• 获取所有编译过程
• 每当 “javac(或其他相关API)” 被调用后,编译获取系统记录所有的编译器选项,操作,源代码与调用的库文件
• 面向源代码和库文件可进行全面编译后分析
• 找到的缺陷将被展示给研发人员修复
如何分析缺陷?
• 过程间分析(Intra-procedural analyses)将考虑每一个合理的可执行路径
• 快速修剪不可行路径是一件很麻烦的事情!
• 数学方案
• 获取一系列的函数定义
• 资源分配
• 调用….
• 过程间分析
• Bytecode 分析将创建函数定义
找到潜在Bug其实只是难题之一
• 消除误报非常难
• 将复杂的缺陷解释出来很难
• 只找潜在的一次性缺陷是很难的
Java 缺陷
Web 应用安全缺陷(OWASP Top 10)
– 跨站脚本攻击
– SQL 注入
– 命令行注入
– 路径遍历…
资源泄露
– 数据库连接资源泄露
– 资源泄露
– Socket & Stream 泄露
并发数据访问异常
– 变量非原子更新
– 双重检查锁定
– 数据竞态条件
– Volatile非原子更新
– Servlet 属性无效锁定
– 单例模式竞态条件
程序假死
– 线程死锁
– 死锁
空指针引用
– Null检查后引用空指针
– 直接引用返回的空指针
– Null检查前引用空指针
API 使用错误
– 无效迭代器使用
– 不可修改的集合错误
– 已释放资源调用
性能缺陷
– 低效率方法使用
– 在循环中连接字符串
– 冗余同步
逻辑错误
– 不可达代码
– 未使用变量
– 常量表达式
– 非本地资源不当使用
– 整数溢出
– 不当分号
类层次结构不一致
– 调用 super.clone() 或 supler.finalize()失败
– 父函数调用丢失
– 构造函数中使用虚函数
控制流缺陷
– 在Finally模块中返回
– Switch语句中break丢失
错误处理缺陷
– 未验证的返回值
数据库操作
– 不正确的实体哈希
– Load函数返回值错误验证
– 不完全持续周期
– get()不当使用
代码可维护性缺陷
– 调用已过期方法
– 显式垃圾收集
– 非静态方法中设置静态变量
– 复制/粘贴错误
– 不可达代码
可疑代码
– 参数次序错误
– 格式错误
C# 缺陷 Powered by Eric Lippert
资源泄露
– 数据库连接资源泄露
– 资源泄露
– Socket & Stream 泄露
API 使用错误
– 已释放资源调用
并发数据访问异常
– 变量非原子更新
– 数据竞态条件
性能缺陷
– 低效率方法使用
– 在循环中连接字符串
– 冗余同步
程序假死
– 线程死锁
– 死循环
可疑代码
– 复制/粘贴错误
– 参数次序错误
– 格式错误
类层次结构不一致
– 调用 base.close() 或 base.dispose()失败
– 父函数调用丢失
控制流缺陷
– 可疑的额外分号
– 不一致比较
– 不兼容的类型比较
空指针引用
– Null检查后引用空指针
– 直接引用返回的空指针
– Null检查前引用空指针
算术错误
– 错误移位操作
– 不正确的表达式
– 表达式计算过程中溢出
C/C++ 缺陷
资源泄露
• 内存泄露
• Microsoft COM 内存泄露
• Object资源泄露
• 不当delete
未初始化变量
• 返回语句丢失
• 未初始化的指针/标量/数组 读写
• 类或结构体中未初始化的数据成员
并发缺陷
• 死锁
• 竞态条件(Race conditions)
• 阻塞调用误用
算术错误
• 负变量不当使用
• 异常符号扩展
• 整数溢出
• 除零异常
内存崩溃
• 内存访问溢出
• 字符串长度计算错误
• 缓冲区溢出
• 写指针溢出
• 负数组索引写入
• 内存错误分配
• 错误的内存释放
非法内存访问
• 不正确的delete操作
• 溢出指针读取
• 越界读取
• 返回指针至本地变量
• 负数组索引读取
• 已释放指针读/写
• 不兼容的指针转换
控制流缺陷
• 逻辑/结构死代码
• Switch语句中break遗失
• 非本地资源不当使用
程序假死
• 死循环
• 双重锁或解锁丢失
• 负循环边界值
• 线程死锁
• 持锁过程中调用sleep()
空指针引用
• Null检查后引用空指针
• 直接引用返回的空指针
• Null检查前引用空指针
错误处理缺陷
• 未验证的返回值
• 未获取异常
• 负变量不当使用
代码维护性缺陷
• 多返回语句
• 无效变量
异常代码
• 复制/粘贴错误
• 格式错误
不安全的数据处理
• 不可信的循环数据源
• 使用非可信数据源读写数组/指针
• 使用非可信数据源格式化字符串
性能缺陷
• 值传递大参数
• 使用大堆栈
安全措施违反
• 缓冲区溢出
• 固定长度缓冲区写入
• 非安全函数调用
• 非安全临时文件使用
• 检查/使用时间不一致
• 用户空间指针不当使用
API错误使用
• 非安全chroot调用
• 错误的迭代器使用
• printf() 参数不匹配
检测实例-HeartBleed Bug
Jenkins检测对比
Freeradius缺陷检测对比
——————————————————————————————————————————————————————————————————————————
希望对您公司企业信息化IT架构与研发管理体系等有帮助。 其它您可能感兴趣的文章:
移动应用App测试与质量管理一
全面的软件测试
著名ERP厂商的SSO单点登录解决方案介绍一
软件项目风险管理介绍
企业项目化管理介绍
智能企业与信息化之一
由企业家基本素质想到的
敏捷软件质量保证的方法与实践
构建高效的研发与自动化运维
IT运维监控解决方案介绍
IT持续集成之质量管理
人才公司环境与企业文化
企业绩效管理系统之平衡记分卡
企业文化、团队文化与知识共享
高效能的团队建设
餐饮连锁公司IT信息化解决方案一
如有想了解更多软件研发 , 系统 IT集成 , 企业信息化,项目管理,企业管理 等资讯,请关注我的微信订阅号:
作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。