1 引言
近年来,应用软件随着信息系统的发展,功能随之增大,相应的,程序源代码的规模也加大了,容易被利用的安全漏洞和代码后门也不再局限于以往,这就使得用传统软件测试方法来检测源代码中的安全漏洞非常困难。所以从源代码审计的角度,对源代码进行检测和分析,从而从根本上保护软件和信息系统的安全,杜绝了代码后门又能够避免潜在的漏洞安全威胁,进一步保障了信息安全。
在对应用软件和信息系统进行安全评估的时候,很多问题都是出现在软件的编码阶段,如SQL注入、XML实体攻击、XSS跨站脚本攻击等。这些问题都需要通过修改软件的源代码来解决。因此,对于应用软件和信息系统的安全问题必须从底层的源代码抓起,在其上做到最佳防范。
本文阐述了源代码审计原则,概述了源代码审计的方法和技术,对比了源代码审计工具,表明了源代码审计的价值和意义,最后对源代码审计技术的发展趋势做出预估。
2 代码审计介绍
2.1 代码审计简介
代码审计是一种以发现程序错误,安全漏洞和违反程序规范为目标的源代码分析。软件代码审计是对编程项目中源代码的全面分析,旨在发现错误,安全漏洞或违反编程约定。 它是防御性编程范例的一个组成部分,它试图在软件发布之前减少错误。 C和C++源代码是最常见的审计代码,因为许多高级语言(如Python)具有较少的潜在易受攻击的功能(例如,不检查边界的函数)。
2.2 代码审计对象
代码审计的对象主要是PHP、Java、asp、.net等与Web相关的语言
2.3 代码审计内容
1. 系统所用开源框架
包括反序列化漏洞,远程代码执行漏洞,spring、 struts2安全漏洞,PHP安全漏洞等。 v
2. 应用代码关注要素
日志伪造漏洞,密码明文存储,资源管理,调试程序残留,二次注入,反序列化。 v
3. API滥用
不安全的数据库调用、随机数创建、内存管理调用、字符串操作,危险的系统方法调用。 v
4. 源代码设计
不安全的域、方法、类修饰符未使用的外部引用、代码。
5. 错误处理不当
程序异常处理、返回值用法、空指针、日志记录。 v
6. 直接对象引用
直接引用数据库中的数据、文件系统、内存空间。 v
7. 资源滥用
不安全的文件创建/修改/删除,竞争冲突,内存泄露。
8. 业务逻辑错误
欺骗密码找回功能,规避交易限制,越权缺陷Cookies和 session的问题。
9. 规范性权限配置
数据库配置规范,Web服务的权限配置SQL语句编写规范。
3 代码审计原则
3.1 所有的输入均不可信
在源代码程序存在很多的输入,包括系统内部和外部,由于用户的输入被应用程序处理、分析,然后展示,那么每一个有可能被恶意利用或者造成代码纰漏的输入都是可疑的。据统计,在漏洞里面,由于输入数据引起的安全问题高达90%,所以对于程序代码中数据输入的格式与内容进行严格的规定,能够起到一定的安全控制的作用。
3.2 遵循安全编码规范
遵循安全的编码规范在代码开发阶段很有必要,软件系统因为编码规范、安全,会更健壮,抵抗恶意攻击的能力也会越强。源代码审计制定了相应技术的源代码安全规范,并在审査的过程中检査应用程序是否严格遵从现有的安全编码规范。若是没有遵循安全编码规范,但没有造成漏洞风险,这样的源代码仍然存在安全风险,需要在最后的审计报告中明确指出。
3.3 漏洞与安全编码内在关系
现有的代码安全审计主要是査找传统或者已知代码的安全漏洞,这些安全漏洞主要是一些国际权威组织比如OWASP公布的代码安全漏洞,这些漏洞都是基于不同的安全漏洞模型来査找的,主要使用了数据流、控制流等技术査找恶意数据的入口点和恶意数据可能被利用的点(出口点),利用人工分析从入口点到出口点是否有风险来判断问题是否真实存在,并且所有的入口点及出口点都是基于开发源代码语言的API来査找的,与本身代码的逻辑无关。
CWE是一个社区开发的常见软件弱点的正式列表。它是一种用来描述软件安全弱点的通用语言,一个安全软件用来定位漏洞的标准量尺,以及一个用于弱点识别、缓解和预防所使用的基线标准。CWE作为统一的标准,它无论在广度还是深度方面统一了这一领域最有价值的内容,平衡了学术界、商业界以及政府在思维和认识方面的不同。CWE 的目标是促进代码审计行业的标准化和成熟化,同时大力推进各类组织对他们采购或开发的软件质量进行审查的能力。
3.4 反向思考
在源代码审计的过程中,需要审计人员站在一个恶意用户或者攻击者的角度上反向思考,保持思维的灵活连续,从各个方面对代码的所有问题进行排査,对于异常问题的检査,要考虑到其波及范围和漏洞影响。
4 代码审计工具
4.1 RIPS
RIPS 是最流行的静态代码分析工具,可自动检测 PHP 应用程序中的漏洞。通过对所有源代码文件进行标记和解析,RIPS 能够将 PHP 源代码转换为程序模型,并检测在程序流程中可能被用户输入(受恶意用户影响)污染的敏感接收器(可能存在漏洞的函数)。除了发现漏洞的结构化输出之外,RIPS 还提供了一个集成的代码审计框架。RIPS 能够检测 XSS, SQL 注入, 文件泄露, Header Injection 漏洞等等。
4.2 Seay
Seay源代码审计系统一款基于白盒测试的代码审计工具,具有自动代码审计功能,简化了人工审计的繁琐流程,使代码审计更加智能简洁。并且它基于C#语言开发的一款针对PHP代码安全性审计的系统,主要运行于Windows系统上。这款软件能够发现SQL注入、代码执行、命令执行、文件包含、文件上传、绕过转义防护、拒绝服务、XSS跨站、信息泄露、任意URL跳转等漏洞,基本上覆盖常见PHP漏洞。另外,在功能上,它支持一键审计、代码调试、函数定位、插件扩展、自定义规则配置、代码高亮、编码调试转换、数据库执行监控等数十项强大功能。
4.3 Fortify
Fortify 是一个静态的、白盒的软件源代码安全测试工具。它通过内置的五大主要分析引擎:数据流、语义、结构、控制流、配置流等对应用软件的源代码进行静态的分析,通过与软件安全漏洞规则集进行匹配、查找,从而将源代码中存在的安全漏洞扫描出来,并可导出报告。扫描的结果中包括详细的安全漏洞信息、相关的安全知识、修复意见。
4.4 Checkmarx
Checkmarx提供了一个全面的白盒代码安全审计解决方案,帮助企业在软件开发 过程中查找、识别、追踪绝大部分主流编码中的技术漏洞和逻辑漏洞,帮助企业 以低成本控制应用程序安全⻛险。
5 代码审计前期准备
5.1 熟悉语言结构
代码审计之前,首先需要了解程序的数据结构以及语言的相关细节,如:算法结构、变量、条件判断等,这样在,代码审计的时候可以更深层次的分析代码。
5.2 了解被审计的程序的功能
在开始审计一个程序之前,先要对被审计的程序有一定的了解,知道程序的主要功能,了解被审计程序的基本结构。
5.3 完整拷贝程序代码
在审计软件漏洞之前,先要下载被审计的程序代码,然后使用对应的编译环境对代码进行编译,利用编译环境的的类型安全检查分析,最后将编译完成的程序代码下载到本地,准备开始审计。
6 代码审计流程
6.1 前期准备
- 确定审计对象、方式和时间
- 配置审计分析环境
- 熟悉业务流程
- 分析程序架构
6.2 代码审计实施
- 源代码扫描
- 工具自动化分析
- 人工代码审计
6.3 复测阶段
- 回归检查(即二次复查)
6.4 整理报告
- 整理审计报告
7 代码审计的意义
7.1 简化修补程序
在开发过程中经常会用到开源代码及其他开发人员创建的代码,这些代码在编写规范上或语义语法上存在的问题及风险是未知的。通过早期代码安全测试,可以帮助开发人员第一时间发现安全问题,减少自行查找代码问题的工作量。而且早期进行代码安全测试,存储库中的代码将是安全的,因为这需要开发人员在完成开发任务前解决安全问题,反过来,也降低了重新修补程序的次数。
7.2 加强开发人员安全意识
利用早期代码安全检测,可以避免开发人员提交包含缺陷的代码,降低系统漏洞风险。这也会让开发人员更加重视自己的代码是否安全。因为存在缺陷的代码将无法通过安全检测,强制性的提高开发人员的安全意识。
7.3 避免过早暴露漏洞
有时为了确保版本及时上线而无法延迟,那么就不得不在发现漏洞后被迫继续发布这个版本。可想而知,向公众公开具有严重漏洞的软件有很大风险,同时也可能成为恶意黑客的下一个目标。尽管企业会选择Web应用程序防火墙(WAF)来暂时保护软件,但WAF保护并非万无一失。早期进行代码安全检测,团队不必担心在最后一分钟才发现问题,增强对软件版本安全的信心。
7.4降低返工成本
如果开发人员不小心将严重的漏洞引入应用程序的新功能,而且这个漏洞没有被代码审阅者注意到,并且在SDLC的早期阶段没有自动审计,那么这个问题的严重后果是不可预测的。要消除此漏洞,就不得不延迟发布版本,同时把代码返回给开发人员,然后再进行QA测试,最后再将应用程序从头开始调试,付出巨大的精力和时间。
通过早期代码安全审计可以捕获大多数漏洞并及时被消除,减少因潜在风险导致的意外延迟,也避免在业务上造成重大损失。