【摘 要】 源代码是软件的根本,其存在的安全缺陷是导致软件出现漏洞的根源所在,人为因素的影响使得每个应用程序的源代码都可能存在安全漏洞。从根本意义上来说,代码审计就是挖掘源代码中存在的代码安全问题。本文对源代码安全问题进行分析,阐述了源代码审计方法和流程,通过研究Java Web漏洞产生的原因及源代码表现形式,给出了源代码安全编码原则,总结出消除相应漏洞的安全编码规范。
【关键词】 源代码安全审计 漏洞检测 编码规范 静态检测
1 引言
随着计算机信息技术的发展,应用软件呈现开放化、智能化、融合化、多元化等发展趋势。应用软件由于源代码编写不规范或引用的第三方框架、开源组件存在安全漏洞,从而导致软件中隐藏着安全漏洞或质量缺陷。这些安全漏洞或质量缺陷一旦被攻击者利用,将会威胁软件系统和其应用数据的机密性、完整性、可用性。开放式Web应用程序安全项目(Open Web Application Security Project,OWASP)2017年发布的Web应用安全十大漏洞中有8项和源代码缺陷相关。
应用软件和信息系统的安全问题必须从底层源头出发,进行源代码安全审计,检查代码的安全缺陷,编写是否遵循安全编程规范,开发是否使用了不安全的第三方组件,从而在安全事件发生前或漏洞隐患尚未被利用前有效规避大部分应用程序的代码问题,提高系统的主动安全防御能力。
2 源代码安全审计的方法和流程
2.1 源代码安全审计方法
源代码安全审计的主要目的是提高源代码质量,通过对程序源代码进行检查和分析,发现源代码在软件设计、测试、应用部署等各阶段中可能存在的安全缺陷或安全漏洞,从源头上避免潜在的安全风险。源代码审计技术可分为静态检测(Static Analysis Security Testing,SAST)、动态检测(Dynamic Analysis Security Testing,DAST)及动静结合检测(Interactive Application Security Testing,IAST)。
静态检测是指在不运行程序代码的情况下,对程序中数据流、控制流、语义等信息进行分析,配合数据流分析和污点分析等技术,对程序代码进行抽象和建模,分析程序的控制依赖、数据依赖和变量受污染状态等信息,通过安全规则检查、模式匹配等方式挖掘程序源代码中存在的漏洞。源代码漏洞静态检测方法一般是将源代码转化为单词(token)、树、图等代码中间表示形式,结合不同的检测算法和检测模型进行检测。
动态检测是指向程序输入人为构造的测试数据,根据系统功能或数据流向,对比实际输出结果与预想结果,分析程序的正确性、健壮性等性能,判断程序是否存在漏洞。动态检测技术主要分为3种:模糊测试、动态符号执行和动态污点分析。
动静结合检测是一种将静态分析和动态分析相结合的混合式漏洞检测方法,先使用静态检测方法对大规模的软件源代码进行检测,对大规模的软件源代码进行切分,有针对性地进行检测。再使用动态检测方法对已划分的程序代码进行数据输入,根据数据流向来判断漏洞是否存在。
2.2 源代码静态审计思路
源代码审计的思路有以下3个。根据敏感函数来逆向追踪参数的传递过程,即检查敏感函数的参数,然后回溯变量,判断变量是否可控且是否经过严格过滤;正向追踪变量传递过程,观察是否有变量输入到高风险函数中,或传递的过程中是否有代码逻辑漏洞;通读全文代码,根据自身的经验判断漏洞位置,直接挖掘功能点漏洞。
2.3 源代码静态审计流程
常见的静态分析工具有: CodeQL、Fortify、CoBOT、Coverity、 RIPS、FindBugs、Cppcheck等。依据分析目标的不同,静态分析可分为:面向源代码的静态分析和面向二进制代码的静态分析。面向源代码的静态分析以程序的源代码作为输入,对其进行语法分析、语义分析,并转换为某种特定形式的中间表示,基于该中间表示进行数据流分析、控制流分析等。面向二进制代码的静态分析则是以经过反汇编等手段处理后的二进制代码作为输入,运用模式匹配或补丁对比等方式实现漏洞检测,当程序是以二进制形式发布的,需要使用面向二进制代码的漏洞分析。本文主要研究面向源代码的静态检测技术的原理和流程。
源代码通过编译器进行词法分析、语法分析和语义分析,生成抽象的中间表示,这些中间表示蕴含了源代码的特定信息。例如,在语法分析阶段,语法分析器会产生蕴含丰富语法信息的抽象语法树。抽象语法树中叶子节点用于表示操作数,非叶子节点用于表示操作符,树的层次结构表示代码语句间的嵌套关系。为了更有效地捕获代码的语法、语义及上下文信息,学术界提出使用抽象语法树、控制流程图、程序依赖图等代码的中间抽象表示建立漏洞挖掘模型。源代码审计流程如图1所示。