一种高效检测源代码安全漏洞的代码审查方法

2015-03-31 19:07周诚等
现代电子技术 2015年5期

周诚等

摘 要: 目前代码安全审查和白盒安全测试被广泛用于分析源代码并检测安全漏洞。这里描述一种基于安全特性参照树的更高效的代码安全审查方法,其中安全特性提取于源代码中所有可操作的内容。这种方法只在源代码层面进行安全检查,可以大大减少错误代码行为,并为自动化安全审查提供了有效的解决方案。

关键词: 代码安全检测; 漏洞检测; 代码审查; 参考树

中图分类号: TN915.08?34; TP393 文献标识码: A 文章编号: 1004?373X(2015)05?0083?04

An efficient code audit method to detect source code security vulnerability

ZHOU Cheng, ZHANG Tao, MA Yuan?yuan, LI Wei?wei

(Nanjing Branch, China Electric Power Research Institute, Nanjing 211100, China)

Abstract: The code security audit and white box security testing is widely used to analyze source code and detect security vulnerabilities. In this paper, a more efficient code audit method based on security feature reference tree is described, in which security features are extracted from all operable contents in the source code. This method only checks the security in the source code. It can greatly reduce the error code behavior and provide an effective solution for automate security audit.

Keywords: code safety detection; vulnerability detection; code audit; reference tree

0 引 言

软件漏洞是当今信息系统绝大多数安全漏洞的来源。软件漏洞是软件中存在的一些缺陷,这些缺陷可以被第三方或程序利用来进行未经授权的资源访问,或改变控制权限来执行其他操作。软件漏洞轻则造成相应的经济或财产损失(如敏感信息被盗,不可用的服务),重则导致严重的灾难,尤其是发生在被人类生活和生计所依赖的关键基础设施的软件系统上(如核,生物,化学实验室,电网,水处理和分配系统,空中交通控制和交通信号系统)。

与代码审计有关的前期工作[1?5]多聚焦于缓冲区溢出漏洞。D.Wagner等提出了一种用于发现C语言代码中潜在缓冲区溢出的关键安全性问题的方法[6]。该方法将缓冲区溢出检测转化为一个整数约束问题,并使用一些简单的图论技术构建了一个整数约束求解的有效算法。最后利用安全知识设计一个可以捕捉有可能会在实际程序中出现的安全相关性漏洞的启发式。Vinod Ganapathy等提出了一种将C字符的操作建模为一种线性规划,并根据线性规划的相关文献来确定缓冲区范围的方法[7],来了解并消除源代码中存在的缓冲区溢出漏洞。

1 源代码安全漏洞的检测过程

代码安全审查的对象是实践于应用中的源代码。这些审计的主要目的是发现安全漏洞和缺陷,然后准确地识别与修复。事实上,安全漏洞的概念被引入到软件主要是由于大多数软件及其功能无法在未知情况下保持正常运行。一般来说,攻击者有两个渠道来利用软件的缺陷:一是通过软件的输入;二是通过软件与其他应用层实例之间的接口。

几乎所有的可利用安全漏洞都可以被用于执行非预期的操作,特殊的输入、接口或环境入口会触发这些安全漏洞从而对系统造成破坏。例如,黑客总是构造一些精心设计的字符串作为应用程序的输入来使其崩溃,或改变它的控制流来做其他恶意操作(如拒绝服务攻击,SQL注入和跨站点脚本攻击)。可利用安全漏洞总是与外部输入、接口或其他环境入口相关,所以检测到它们最有效的方式是从外部对操作入口进行性跟踪(如本地输入、网络输入、临时文件或其他输入,接口或其他环境入口,等),通过此方法找到所有可利用安全漏洞。检测源代码安全漏洞过程如图1所示。

第一步,检测和定位源代码中所有的操作入口。这些操作入口包括但不限于用户输入,网络输入项,I/O输入项等。而可以用来检测这些操作入口的方法是找到所有用于获取外界输入、用于与接口和其他环境入口做交互的API(Application Programming Interface,应用程序编程接口)。

第二步,为每个在第一步中定位的操作入口建立一个参考树。每个引用或引申的参考项可以追溯到的节点应该包含在树中。记录和保持原有的安全属性对进一步操作参考树来说是十分必要的,其中安全属性指的是程式化安全规则(FSR)。FSR可以定义不同树的安全性能,它是一种可被机器识别的自动处理过程。FSR包括但不限于正则表达式,ACL,等。

第三步,对参考树的遍历,即遍历树的节点,利用安全属性来检查是否有可利用安全漏洞的存在。该安全漏洞检测方法可以是但不限于,检查父亲的FSR和孩子的FSR之间的矛盾等。

第四步,根据在第三步检测到的安全漏洞来产生告警提示,并提供基于第三步分析的修正建议。

最后,开发人员可以在建议的基础上修改其源代码,并再次执行此过程,以保证修正过程中不会引入任何新的漏洞。

2 一种高效检测源代码安全漏洞的代码审查方法

一种高效检测源代码安全漏洞的代码审查方法总共包括四个模块:操作入口定位器,解析引擎,漏洞检测器和告警修复模块,系统结构如图2所示。

(1) 操作入口定位器

操作入口定位器可以实现(但不限于)通过搜索所有用于接收诸如scanf(),getchar(),getwindowstext,socket输入等外部输入的API(不同的程序语言可能有不同的API)。

(2) 解析引擎

解析引擎利用的是编译器技术,它可以找到所有可以追溯到操作入口的代码块。它可以在句法分析中自动分配一些FSR规则。最后,该引擎将产生源代码参考树,如图3所示。

(3) 漏洞检测器

漏洞检测器将根据源代码参考树进行处理。它会对参考树节点的FSR进行检查,分析是否有任何安全漏洞。

(4) 告警修复

告警修复模块将提供安全漏洞的警告信息,以及修复被探测器探测到的安全漏洞的建议。分析模块将从根节点开始遍历参考树,并与每个节点的孩子节点比较FSR。当它检测到任何安全漏洞,分析模块会产生警告,并给出修复建议。用于实施该方法的伪代码如下:

BuildTree(Father)

{

Searching Relevant Child

For Each Relevant Child

{

Generate Its Formulated Security Restriction(FSR);

Record Its FSR and Position Info;

Insert It into the Tree as Child?Node of Father;

BuildTree(ThisChild);

}

}

Main( )

{

Searching All Manipulable Entries

For Each Entry

{

Generate Its Formulated Security Restriction(FSR);

Record Its FSR and Position Info;

Insert It into the Tree as Root of Father;

BuildTree(ThisEntry);

}

For Each Built Tree

{

Post?order Traversal All Nodes of Tree from LeafNode;

Detect Where Child.FSR is Stricter than Father.FSR;

Generate Warning;

Indicate Suggested Father.FSR to Follow Strictest Child.FSR;

}

For Each Entry

{

Post?order Traversal All Nodes of Tree from Root;

Detect Where Child.FSR is Stricter than Father.FSR;

Generate Warning;

Indicate Suggested Those Child.FSR to Follow Father.FSR;

}

}

3 应 用

3.1 情景一:代码注入漏洞

代码注入指的是外部代码被直接插入到程序或脚本中被执行。一般可执行代码被注入前先插入到非可执行的文本串中,然后再提交给应用程序,

代码注入是通过在本应该不可执行的文本字符串中嵌入可执行代码引起的。有两种方法来定义的FSR:一个是定义的字符串的属性为非可执行;另一种方法是指出不应该包含在文本中的字符串,包括任何可执行的“关键字”,或表达式中的字符串(如脚本标签出现,或SQL请求中出现单引号?(′)或双破折号(——))。在这里,选择了第二种方法,其可以指定FSR的格式为[FSR:限制规则]。

内容限制可以通过正则表达式来执行。例如,“^.$”可以表示所有可能的字符串,这可以表示所有外部原始输入。在将外部输入命令转化为SQL查询命令时,可以设定此内容限制,即不包含SQL特定字符,具体命令格式如下:

图4所示的是通过解析引擎建立的参考树。所有节点都将被编号为n.n,这体现了父节点和子节点之间的关系。同时,该节点的FSR和位置信息也将被记录下来。安全性分析模块将通过检查每个子节点的FSR是否与其父节点一致来处理参考树。一种解决方案是从参考书中的叶节点开始遍历,比较它们与父节点的FSR。例如,在图3中,节点1.2.2是一个节点1.2的子节点,其FSR中的“的”意味着不应该包含任何SQL相关的特定字符,但它的父节点(节点1.2)的FSR为“”,这意味着它可能包含所有可能的字符,包括SQL相关的特定字符。所以在这里发现了一个安全漏洞,系统的告警和修复模块会产生警告,并产生诸如“节点1.2需添加字符串验证”这样的修复建议。

3.2 情景二:缓冲区溢出漏洞

一般来说,当一个数据块B写入缓冲器A时,若B的大小大于A的合法分配的大小就会发生缓冲区溢出。缓冲器溢出的另一种形式是整数溢出,这是程序的一种潜在问题,即程序中保存的数据大小是通过以字节为单位的数据类型限制的。在这里指定FSR的格式为{FSR:."^{length}$"}。

图5展示了它通过解析引擎建立的一棵参考树。所有节点都将被编号为n.n,这体现了父节点和子节点之间的关系。同时,该节点的FSR和位置信息也将被记录下来。安全性分析模块将通过检查每个子节点的FSR是否与其父节点一致来处理参考树。一种解决方案是从参考书中的叶节点开始遍历,比较它们与父节点的FSR。例如,在图6中,节点1.2有两个子节点,子节点1.2.1和1.2.2,他们允许的最大缓冲区长度为30和20。因为它们的父节点(节点1.2)的允许长度为50,所以当子节点到父节点之间可能会发生溢出。于是在这里发现了一个安全漏洞,系统的告警和修复模块会产生警告,并产生相关修复建议如“建议修改节点1.2的最大缓冲区长度为20”,如图6所示。

3.3 情景三:特权提升漏洞

特权提升漏洞允许攻击者或代码获取其本不应有的更高水平的权限。这里的特权可能不仅代表用户(如管理员,超级用户或访客)的特权,也代表代码(如内核或用户模式)的特权。因此,可以使用访问控制列表(ACL)来分类处理这样的的漏洞。

3.4 情景四:信息泄露或数据篡改漏洞

信息泄露和数据篡改漏洞允许非法用户或代码修改系统内的数据,以实现恶意攻击或将受保护的数据暴露给到没有权限访问该数据的用户。对于这些漏洞的FSR规则也在ACL中有描述。

4 结 语

本文中所描述的方法可以大大降低误报率,并且提供了一种有效的、仅通过检测可利用的安全流量对源码进行自动化安全审计的解决方案。这种方法避免了检测攻击者无法通过输入操作、接口或者其他环境条件进入的不可利用性安全流量,从而可以减少源代码审计分析的开销,尤其是对于大型应用程序。基于参考树的FSR信息,该方法也可以对修改有漏洞的源码提供精确的指导。

参考文献

[1] 徐有福,文伟平,万正苏.基于漏洞模型检测的安全漏洞挖掘方法研究[J].信息网络安全,2011(8):72?75.

[2] DHURJATI D, ADVE V S. Backwards?compatible array bounds checking for C with very low overhead [C]// Proceedings of the 28th International Conference on Software Engineering. Shanghai, China: [s.n.], 2006: 162?171.

[3] 赵国亮,蒋勇,孔令兵.用代码分析技术检测软件缺陷[J].计算机工程与设计,2011(8):2741?2744.

[4] 戴凌宸,张朕荣,黎丰泽.传统的软件测试方法浅析[J].科技风,2011(16):53?55.

[5] 陈晓芳.几种常见软件可靠性测试方法综述及应用对比[J].科技信息,2007(17):6?8.

[6] 董洁,孙惠娟.软件测试方法及面向对象软件的测试[J].河南科技,2011(17):22?23.

[7] WAGNER D, FOSTER J, BREWER E, et al. A first step towards automated detection of buffer overrun vulnerabilities [C]// Proceedings of ISOC Network and Distributed System Security Symposium. [S.l.]: ISOC, 2000: 1?15.

[8] GANAPATHY Vinod, JHA Somesh, CHANDLER David, et al. Buffer overrun detection using linear programming and static analysis [C]// 10th ACM Conference on Computer and Communications Security. [S.l.]: ACM, 2003: 1?19.