前言
随着互联网的高速发展,各类新型Web攻击层出不穷。NIST(美国国家标准与技术研究院)的研究表明,在软件开发生命周期中,在软件发布以后进行修复的代价是在软件设计和编码阶段即进行修复所花代价的30倍,所以在软件系统发布后才发现系统缺陷,然后再去进行修复,这样的代价是很大的。如何在软件系统发布前找到Web应用系统存在的隐藏漏洞已成为众多企业普遍面临的问题。代码审计便是在攻击发生前通过审查源代码的方式,找到系统中的隐藏漏洞。这十分考验代码审计人员对漏洞原理的掌握以及对开发语言的熟悉程度。
伴随Java语言的发展,现在越来越多的程序采用Java语言进行编写。传统的代码审计人员往往对PHP代码审计很熟练,Java开发人员也并不了解所有常见的漏洞,因此写一本有关Java代码审计的书籍便变得尤为重要。
对于渗透测试人员来说,掌握代码审计应是一项基本技能,只有懂得了漏洞的原理以及产生的过程,才能够根据具体漏洞环境的变化写出符合实际需求的攻击代码进行渗透。对于代码审计人员,只有充分挖掘当前代码中可能存在的安全问题,才能使开发人员了解其开发的应用系统可能会面临的威胁,并正确修复程序缺陷。在网络安全竞赛中有一个常见考点:由源代码泄露产生的代码审计。这在实际攻防渗透中也很常见,即由于系统配置或管理员的错误操作而导致系统的源代码泄露。除了源代码泄露,在实战中另外一个场景是目标站点使用了某套开源系统,这时我们除了查找此开源系统已公开的相关漏洞,还有一个十分有效的攻击手法是对此开源系统进行代码审计,以发现未知的漏洞,通过未知漏洞进行攻击。
代码审计需要通过阅读源代码的方式找到隐藏的安全问题,因此代码审计对渗透测试人员的编程能力有一定的要求,而最基础的要求是能够读懂代码逻辑、读懂代码的功能。高中时期我的数学老师曾说过的一句话使我印象深刻——他说:学习是一通百通的,当你学好数学后你就能学好物理、学好化学或是其他的任何一门课程,因为学习的方法是一样的。这句话同样适用于编程语言的学习,大家在校时或多或少都学过C、Python等编程语言,只需将这种编程思想套用到Java语言的学习中即可快速学会它。因此本书更加关注的是怎么写源代码会产生漏洞,这个漏洞为什么会产生,这个函数为什么是不安全的;而不是关注要实现这个功能我们应该怎么写源代码。对于代码审计的常规手法,一般可分为以下三种。
(1)通读源代码:这种审计手法往往能够发现隐藏较深的安全问题,一般从程序的入口函数开始读。但其缺点也十分明显,需要通读整个源代码的逻辑,因此十分耗费时间。
(2)关键函数回溯:这种方法比第一种方法效率大大提升,但是很难发现隐藏极深的安全问题。对于关键函数回溯法,首先需定位到敏感函数以及参数,随后同步回溯参数的赋值过程,判断是否可控以及是否经过过滤等。
(3)追踪功能点:这种方法需要审计人员有一定的渗透测试基础,根据自己的经验判断可能存在问题的路由或功能点,并针对该功能点进行通读。例如,文件上传漏洞可直接通过定位上传函数来发现。
对于一个专业的代码审计人员,审计流程可以分为以下四个步骤。
(1)前期准备阶段:通过由测试人员提供、GitHub、Gitee、CSDN、SVN、源代码泄露漏洞等各类途径获取程序源代码,并搭建相关环境。对于审计环境的准备,我们将在后面的章节做详细介绍。
(2)代码审计阶段:可以先通过奇安信代码卫士、Fortify等自动审计工具对源代码进行扫描,并根据程序提示有目的地进行测试。当扫描工具测试不全或是无可用的扫描工具时,可以根据常见关键字对程序进行全局搜索并定位可能存在问题的程序段。当然,也可以完全从入口函数开始通读所有的源代码。
(3)POC编写阶段:当通过代码审计找到安全问题后,要做的便是根据审计结果以及触发方式编写可行的概念性验证(POC)脚本,通过POC脚本来进一步确定问题以及会造成的影响。
(4)报告编写阶段:根据前面发现的安全问题以及概念性验证(POC)脚本的验证结果,编写整体的代码审计报告,以方便他人查阅。
编著者
2021年7月