SAST工具的核心原理是通过对源代码进行静态分析,构建程序的抽象模型,并基于预定义的安全规则对其进行扫描和检查。其中,抽象语法树(AST,Abstract Syntax Tree)是实现工具自动化安全审计不可或缺的基础。AST是源代码结构的一种树状表现形式,它去掉了源代码中的语法细节(如分号、括号等),仅保留程序的逻辑结构,使得SAST工具能够更高效地分析代码,定位潜在的安全问题。
除此之外,SAST工具还会应用多种代码分析技术,包括:
● 数据流分析:跟踪变量的赋值和使用,检查是否存在未经验证的用户输入、敏感信息泄露等问题。
● 控制流分析:分析程序的执行路径,发现可能导致程序异常或逻辑错误的代码。
AST的生成过程包括:词法分析、语法分析、语义分析。
词法分析(Lexical Analysis)阶段主要任务是将源代码转换为Token序列,Token是源代码中的基本单位,例如关键字、标识符、字面量(程序中的固定值)、操作符等,词法分析的核心是定义构成有效Token的规则,包括:
● 字母、数字、下划线等字符的组合规则,用于识别标识符(如变量名、函数名)。
● 关键字的列表,如“if”“while”“for”等,用于识别特定的语言结构。
● 操作符的定义,如算术运算符(+, -, *, /)、比较运算符(>, <, ==)等。
● 字面量的格式,如整数、浮点数、字符串等。
● 用于分割不同语法元素的分隔符,如圆括号、大括号、分号、逗号、冒号。
这些规则集合定义了哪些字符序列可以构成有效的Token。词法分析器(Lexer)根据这些规则将源代码分解为一个个独立的Token,并标记其类型。
其过程就像看到一句英文语句时候把它分解为单词,比如:
The quick brown fox jumps over the lazy dog
→
["The","quick","brown","fox","jumps","over","the","lazy","dog"]
大脑在处理句子的时候会将其分解成一个个的单独的单词来识别,识别规则(或语法)就是词法分析的规则集。
例如以下代码对应的Token序列生成过程:
根据规则集,上述代码中int、for识别为关键字(Keyword)类型的Token,sum、i、System、out、println识别为标识符(Identifier)类型的Token,0、1、10、“Sum:”识别为字面量(Literal)类型的Token,=、<=、++、+=、+识别为操作符(Operator)类型的Token、;、(、)、{、}识别为分隔符。
语法分析(Syntax Analysis)是编译器或静态代码分析工具中的一个重要阶段,它的主要任务是根据语言的语法规则分析Token序列,检查Token的组合是否符合特定的语法规则,即检查代码的语法正确性,并最终构建抽象语法树(AST)。
语法分析的大致处理过程,是先定义语法规则,这个规则指定了Token如何组合成合法的程序结构,如表达式、语法、函数等,比如Java语言的语法规则类似这样:
其次,是通过语法分析器根据语法规则对Token序列进行分析(包括自顶向下解析和自底向上解析),在分析过程中如果发现Token的组合不符合语法规则,则会报语法错误。
最后,在Token序列无误之后构建抽象语法树(AST),AST的节点表示程序的各个部分之间的关系。比如上述代码的AST结果类似这样:
上面AST中的主要节点VariableDeclaration表示变量声明、ForStatement表示for循环语句,包括初始部分ForInit、更新部分ForUpdate和循环部分Statement等等,还有ExpressionStatement表示表达式语句、AssignmentExpression表示赋值语句、AdditiveExpression表示加法表达式、PrimaryExpression表示字面量等基本表达。
同样类比英语的语法理解,英语句子有主谓宾结构和时态语态,编程语言的语法规则定义了代码的结构和组成。语法分析器就像我们理解英语句子一样,通过语法规则来理解代码的结构,并构建出表示该结构的AST。比如:
"The quick brown fox"是一个名词短语,"jumps over the lazy dog" 是动词短语。
语义分析(Semantic Analysis)是在语法分析结果的基础上分析程序的语义,检查代码的逻辑正确性和一致性,在这个阶段会进行类型检查、作用域解析、变量声明等,因为语法正确并不代表代码逻辑正确,比如3 + "hello"是在语法上是正确的,但语义上是错误的,因为数字不能与字符串相加。如果发现语义错误,如类型不匹配、变量未定义,则会在这个阶段报告。
类比英语的例子,"The fox jumps over the dog"在结构上是对的,但如果我们写"The fox jumps over the moon",尽管语法上没有错误,但语义上存在逻辑问题。
当我们拿到了源代码的抽象语法树,并将其数据格式化存储之后,需要一套高效的算法对漏洞模型进行匹配,这个过程需要引入污点分析技术来对漏洞进行定义。
污点分析的处理过程可以分为三个阶段:
1. 污点源识别(Taint Source Identification)
污点源指的是程序中可能引入不可信数据的位置,比如用户输入(命令行参数、环境变量、配置文件)、网络数据(HTTP请求、Socket接收的数据)或者程序从其他地方读取的数据,比如数据库中的数据、外部文件的内容等。污点源识别的重点在于识别程序中类似以上的代码位置。
2. 污点传播分析(Taint Propagation Analysis)
污点传播分析中的“传播”二字不如英文Propagation(繁殖)精准,它指的是污点识别后,跟踪污点在程序中的传播、流动和演变,这个阶段需要分析污点数据经过的路径和所涉及的操作,也就是程序的数据流是如何通过控制流的,污点传播路径和污点状态可以为后续漏洞检测提供依据。这个过程中污点最终会汇聚到某个程序的控制操作上,也就是污点传播的终点,这个终点往往就是接下来进行漏洞检测和分析的关键,也被称之为污点槽或污点汇(Taint Sinks)。
3. 漏洞检测(Vulnerability Detection)
漏洞检测阶段是利用污点分析的结果,识别程序中潜在的安全漏洞,识别方式依然会使用到漏洞规则匹配或模式匹配的方法。如果污点在传播过程中经过某些控制流的处理使得污点消除或污点净化(Sanitization),则这个污点数据会变得安全,规避了漏洞产生的可能。因此,对于中大型软件的污点分析,其难点之一便是净化函数的识别,其次还包括数据流、控制流分析(如反射调用),因此污点分析也会存在误报情况。
下面代码是污点分析不同阶段的简单示例:
接下来,笔者将对比五款主流的SAST工具,对它们的优势和劣势进行比较,帮助您在选择正确的工具时做出快速决策。对比基准和结果参考了OWASP中国发布的《静态源代码安全分析工具测评基准2.0》以及洞源实验室发布的《静态源代码安全扫描工具测评结果汇总》。
每个工具的对比维度笔者均采用星级评分方式,从一星到五星不等,星级越高表示推荐指数越高,以下是各星级推荐指数的解释:
★★★★★:该工具具备非常高的价值,广泛适用于多种使用场景,性能、功能、用户体验等方面表现突出,适合所有用户使用。
★★★★☆:整体表现优异,但可能在少数功能或特定场景下稍有局限,适合多数用户使用。
★★★☆☆:工具较为实用,基本功能完整,但可能在用户体验、性能或特定应用领域存在一些不足,适合有特定需求的用户使用。
★★☆☆☆:仅能满足基础需求,可能存在明显的功能缺失或性能问题。一般仅适合特定场景或入门级用户。
SonarQube是一种流行的开源SAST工具,可为代码质量和安全分析提供全面的解决方案,其主要优势之一是支持多种编程语言,使其成为使用不同技术的开发团队的多功能选择。SonarQube与各种CI/CD工具无缝集成,支持作为开发管道一部分的自动化代码分析。
SonarQube同时也是一个开源的代码质量管理系统,支持超过27种编程语言的代码质量检测与分析,另一个显著特点是它能够在集成开发环境(IDE)中提供实时通知,允许开发人员在编写代码时立即收到有关潜在安全问题的反馈。此外,SonarQube提供详细的代码质量见解,使团队能够保持高标准的代码卫生和安全性。
● 支持多种CI/CD平台(Jenkins、GitLab CI等)
● 提供本地IDE插件实现开发阶段检查
● 部署灵活,支持云服务和私有部署
支持手动安装,支持Windows、Linux、macOS和Docker容器安装等方式安装,Docker安装过程非常简单,所以这里的推荐指数为5星。
规则集编写:
● 支持自定义规则
● 提供详细的规则文档
● 可使用Java编写自定义规则
规则引擎包括可靠性规则、安全性规则、可维护性规则、编码规范。
该工具的规则编写有点类似于Burpsuite插件开发,通过导入原生的sonar规则的SDK,通过SDK提供的Java工具类将源代码分解为数据并保存存储起来,然后使用Java代码来操作数据做过滤筛查,不论是39行的过滤方法的参数的个数还是49行中判断返回类型是否为“void”都是使用最简单的判断来实现。
上述代码是笔者根据原规则改写的一个检测代码质量的规则,这个规则的意义在于确保方法的设计符合良好的编程习惯,避免返回值和参数类型相同可能导致的混淆或错误。
规则编译起来也是非常简单,简单的打包mvn clean && mvn package -Dmaven.test.skip=true即可。将打出的jar包放到extensions\plugins目录中重启SonarQube,在规则中便可以搜索到添加到规则。
规则集(Rule Set)通常在语法分析和语义分析阶段起作用,具体而言,它对语法结构和语义逻辑进行验证和限制。
Checkmarx CxSAST是一款功能强大的SAST工具,擅长提供深入的静态代码分析。其突出特点之一是集成了人工智能(AI)技术,从而提高了漏洞检测的准确性并减少了误报。
● 支持主流CI/CD工具集成
● 支持SonarQube工具集成
● 增量扫描能力强,支持按需扫描
● 配置相对复杂,需要专门的管理员维护
支持手动安装,但安装过程比较复杂,支持Windows Server、Linux操作系统,也支持云部署,可以在AWS、Microsoft Azure和Google Cloud等平台上运行但是需要付费。
规则集编写:
● 支持自定义规则
● 提供详细的规则文档
● 可使用CxQL编写自定义规则
Checkmarx使用CxQL(Checkmarx Query Language)来编写规则,CxQL允许用户深入代码结构并进行模式匹配。
登录Checkmarx控制台后,进入Queries(查询)模块就可以选择现有的规则集,或者创建一个新规则集,CxAuditor是一个编写CxQL的解释器,在CxAuditor中可以自定义规则,从而替换和扩充checkmarx原有规则。在CxAuditor中,位于“Cx”下的规则为Checkmarx原有规则,用户只可查看,不可编辑。可以通过CxAuditor来修改和扩充Checkmarx规则,CxQL和SQL语句比较相似。
以下是笔者对SQL和CxQL的语法进行的对比,大家可以感受这二者的不同与相似之处:
SELECT类比:SQL中的SELECT用于选择列,而CxQL中的SELECT用于选择代码元素或数据流元素。
FROM类比:SQL中的FROM指定数据表,而CxQL中的FROM可以指定代码的源头或汇点(如输入、函数调用等)。
WHERE类比:SQL中的WHERE用于条件过滤,CxQL也通过WHERE子句指定代码或数据流元素的特定属性或关系。
以下是笔者写的一个简易的CxQL用于检测SQL注入漏洞规则Demo,其中“input”和“sqlQuery”和常规代码中声明的变量起一样的作用,都是用来承载数据的,input是承载了所有用户可能输入的参数值,而sqlQuery承载的是SQL执行的所有函数,而WHERE input -> sqlQuery AND sqlQuery.GetProperty("text").Contains(input.GetProperty("parameters"));表示从用户输入input到SQL查询sqlQuery的数据流中产生的数据是否会包含之前用户所输入的值,比如用户输入一个“XSS”,而sqlQuery查询时候是否会包含“XSS”。
CxQL非常的简单,只需要了解SQL语句的运行机制,就可以复刻到该规则中来,但是需要对基本对CxQL函数有一定的了解。
规则集(Rule Set)通常在语法分析(Syntax Analysis)和语义分析(Semantic Analysis)阶段起作用,具体而言,它对语法结构和语义逻辑进行验证和限制。
代码扫描与GitHub Actions和用户现有的CI/CD环境集成在一起,为团队编程提供最大的便捷度。在代码被创建时进行扫描,并拉取请求以及用户日常使用的其他GitHub服务中可操作的安全性审查,自动化任务的一环。
GitHub代码扫描是集成到GitHub平台中的原生SAST解决方案,为托管在GitHub上的存储库提供无缝的安全扫描。其主要优势之一是与GitHub工作流的轻松集成,允许开发人员在不离开其熟悉的开发环境的情况下利用安全扫描功能。
GitHub代码扫描会自动触发对拉取请求和推送事件的扫描,提供有关潜在安全问题的实时反馈。它支持各种账户层,使不同规模和预算的团队都可以访问它。
但GitHub代码扫描仅限于GitHub生态系统,可能不适合使用其他版本控制系统或开发平台的组织。此外,虽然它提供了基本的安全扫描功能,但它可能缺乏专用SAST工具中的深度和高级功能。
● 与GitHub完美集成,可直接在PR中查看问题
● 配置简单,基于GitHub Actions实现自动化
● 仅限GitHub平台使用,不支持其他代码托管平台
GitHub代码扫描(GitHub Code Scanning)是GitHub的一项内置功能,允许用户在代码库中发现并修复安全漏洞。要安装和配置GitHub代码扫描,需要打开代码扫描的GitHub仓库。
在项目根目录中,创建一个名为.github/workflows的目录,在该目录下创建一个新的工作流文件(例如codeql-analysis.yml),使用起来非常简单。
规则集编写:
● 基于CodeQL,规则编写能力强
● 需要掌握CodeQL语言
● 社区规则集丰富
GitHub Code Scanning使用CodeQL编写规则,而CodeQL类似于SQL,它通过查询语句来分析和检测代码中的安全漏洞和问题。可以将CodeQL查询语言的规则编写理解为SQL查询,通过“查询代码数据库”过滤不符合预期的代码模式。
上述语句中就是简单的匹配“equal”或者“getResourceAsStream”等等字段的简易demo。
导入到GitHub项目中也非常简单,在项目根目录中,将查询命名为insecure_exec.ql,并保存到上一步创建的文件夹中.github/codeql/queries/javascript/security/1.ql,创建一个名为.github/workflows的目录。通过github/workflows/codeql-analysis.yml配置就可以使用自定义编写的CodeQL规则了。
如果对CodeQL感兴趣,可以阅读洞源实验室的《CodeQL:探索代码安全的利器》,文中有更深刻利用和讲解。
通过CodeQL规则对其开源项目扫描,其缺陷结果清晰明了,点击缺陷可以查看代码具体的缺陷位置,这是常规SAST产品都具备的功能。由于GitHub自带的CodeQL规则库数量较专业的SAST产品来说较少,所以针对的缺陷种类是不如传统的SAST的,这里推荐指数给到了2星。
Fortify静态代码分析器是一个全面的SAST工具,支持广泛的编程语言。它提供详细的安全规则和策略,使团队能够根据其特定的安全要求定制分析。Fortify还提供强大的bug跟踪和分类功能,有助于有效管理已识别的漏洞。
Fortify通过调用语言的编译器或者解释器把前端的语言代码(如JAVA,C/C++源代码)转换成一种中间媒体文件NST(Normal Syntax Tree),将其源代码之间的调用关系、执行环境、上下文等分析清楚。
● 完整的DevSecOps工具链集成
● 支持IDE插件和CI/CD集成
● 部署和配置较重,需要专业团队支持
由于与开发环境相辅相成程度非常高,工具支撑线推荐程度给5星。
支持手动安装,支持的Windows、Linux操作系统安装。手动安装过程非常简单,所以推荐指数为5星。
规则集编写:
● 规则体系完善但封闭
● 自定义规则难度大
● 维护成本高
Fortify官方的.bin文件是加密的,无法查看,要编写自定义规则,可以使用Fortify内置的规则编辑器,必须在图形界面下才能运行规则编辑器,编辑器位于Fortify安装目录/bin下,名为CustomRuleEditor.cmd。
Fortify官方认可的安全库函数如下图:
其实上述配置XML的过程与写代码是类似的操作,只不过Fortify使用自定义的XML解析器,其实后台还是还原成代码或者CodeQL语句,上述规则旨在检测潜在的命令注入漏洞,特别关注在Java应用程序中使用java.lang.Runtime.exec()和java.lang.ProcessBuilder.start()方法的场景。
将编写好的rule.xml移动到软件默认的目录,然后重启软件客户端,Fortify虽然使用了XML的格式,但是XML的解析器无法修改,只能在Fortify的规则内进行规则编写,确实有一定的限制,所以推荐指数3星。
Fortify的漏洞误报率和漏洞漏报率,可参考洞源实验室《静态源代码安全扫描工具测评结果》。
无论是源码扫描的速度,还是代码缺陷的准确率还是在代码输出报告的方便性来说,都是常规SAST产品中较为优质的产品,这里推荐指数给5星。
Snyk是一个以开发人员为中心的SAST工具,专注于在开发过程中提供实时安全反馈。它提供了快速的漏洞识别和修复指导,使开发人员能够及时解决安全问题。Snyk支持广泛的语言和框架,使其适用于多样化的开发环境。
Snyk的功能仅限于支持的语言和环境。此外,有用户报告该产品存在较高的漏洞误报率,需要在使用过程中仔细审查和验证已识别的漏洞。
● 开发阶段就可以通过IDE插件发现问题
● 与代码托管平台集成良好
● CI/CD集成配置简单直观
● 规则主要聚焦安全漏洞
● 自定义规则能力有限
● 规则更新及时
几乎支持当前市面上所有的CI/CD产品的集成,这里推荐指数给5星。
支持手动安装,支持Windows、Linux操作系统安装,但是该软件属于商业软件,笔者目前还没有找到可以下载安装的免费版Snyk版本,所以使用了官方提供的API进行测试。这里推荐指数给出三星。
不支持直接导入自定义规则,推荐指数给出一星。
不论是IDEA的插件还是上传源代码,都是通过API进行完成的,相同的靶场代码,使用默认的规则扫描出来的漏洞较少。
故推荐指数给3星。
以上工具各有所长,在不同的开发和安全需求下各有优势。
如果比较重视代码质量管理,并且在CI/CD流程中关注质量把控,那么可以选择SonarQube这款SAST作为主要的代码质量审核工具。
如果需要的是擅长企业级静态分析,特别是在高安全需求的项目中表现出色,那么最好选择Checkmarx,其专有的Checkmarx Query Language(CxQL),允许高度自定义的安全检测规则,可以针对企业中各种专有的问题制定对应的规则来解决独有的问题。
如果开发开源项目又担心开源代码存在安全问题,那么GitHub Code Scanning是最好的选择,利用CodeQL在项目中发现漏洞,适合开源项目和DevOps流程。
Fortify提供全面的安全扫描,支持静态、动态及实时保护,与Checkmarx一样适用于大型组织和严苛的合规环境,只不过Fortify比CxQL的自定义规则灵活度稍逊一筹。
最后,Snyk是开源安全管理的领先工具,能有效检测依赖性漏洞,适用于需要管理开源依赖和容器安全的开发团队。
扫码添加安仔微信,邀请进群
与行业专家深入交流探讨~