SAST入门
SAST
SAST所涉及到的内容:
SAST (Static Application Security Testing) 的核心原理
简介
SAST 是一种白盒测试方法。它通过在不实际执行应用程序代码的情况下,对源代码、字节码或二进制代码进行分析,以识别安全漏洞
“静态”:指在代码静止不动(未运行时)进行分析
“白盒”:指工具拥有并能够查看应用程序的全部内部结构和逻辑(即源代码)
常用工具
- Checkmarx SAST
Checkmarx SAST拥有SAST工具中最友好的Web用户界面,同时还整合了很多高级功能。即使是那些对软件开发中的安全问题不熟悉的人,也能在这个界面的帮助下快速成长。Checkmarx不仅会识别漏洞,还会对漏洞的危险性做出解释。只需按下一个“最佳修复位置”按钮,开发人员就可以深入了解消除这些问题的最简单、最有效的方法。
Checkmarx开箱即用,支持超过25种编程语言,可配置为作为CI/CD管道的一部分自动运行,或者设置自定义查询并根据需要运行。它还可以适应任何主流IDE或源代码管理平台
- CyberRes Fortify (原 Micro Focus Fortify)
CyberRes Fortify平台同时提供SAST和DAST功能。作为SAST产品,它的可视化界面非常干净简洁,可以很直观地向开发人员展示代码中的特定漏洞以及定期发现的漏洞种类的统计信息(分为810个漏洞类别)。然后,它将开发人员引导至其游戏化的培训界面,该界面使学习安全知识和编写安全代码变得轻松有趣。
该平台支持27种编程语言和框架,可以在本地部署或用作服务,还可以集成到大多数主流IDE中,例如Eclipse和Visual Studio
- Perforce Klocwork SAST
Perforce Klocwork SAST号称即使在最庞大的开发环境中也能提高速度。它适用于用C、C++、Java、JavaScript和Python程序,以及Docker容器。它可以集成到任何主流IDE中,如Visual Studio Code、IntelliJ等。
该工具的开发人员声称,他们设计Klocwork是为了弥补SAST工具的差距,使其能够在复杂的环境中运行。用户可以使用Klocwork扫描多达数百万行代码组成的大规模代码库。Klocwork使用了一些技巧来进一步减少扫描时间,比如每次只扫描更改的代码区域而不是整个程序。
Klocwork甚至还能帮助对开发人员进行安全培训。它可完全集成到负责安全和意识培训的Secure Code Warrior培训平台中。因此,Klocwork不但可以发现和修复代码中的问题,还能培训开发人员。
- Spectral SpectralOps Platform
Check Point最近收购了Spectral,但仍在积极支持SpectralOps平台,这可能是因为其独特的SAST功能。SpectralOps可以找到开发人员在开发过程中经常硬编码到程序中的API密钥、凭据和令牌等敏感信息。通过查找这些敏感信息和错误安全配置,可以防止程序在开发过程中被恶意用户未授权访问,对于已经部署的应用程序也是如此。
SpectralOps在软件开发生命周期的每一个步骤都会不断扫描,使用人工智能技术跟踪超过2,000个检测引擎。SpectralOps采用其他测试方法来确保发现可疑情况时不会产生误报。之后,它可以通过各种通信平台向Slack报告其发现、发布JIRA工单或提醒开发人员
- Veracode Static Analysis SAST
Veracode静态分析SAST平台是一种云服务,这避免了在本地环境中维护SAST应用程序的复杂性。Veracode采用即时学习原则,可以将易受攻击的代码标记为开发人员正在编写代码。修复代码后,工具可以生成报告,企业可以根据这些报告来表彰那些安全意识较好的开发人员,并通过积极的强化来激励他们。
除了集成到主流IDE之外,Veracode还注重速度。可以自动扫描程序或应用程序的每个组件,平均扫描时间仅为90秒。而且Veracode平台还能细致地跟踪测试工作,并在在线门户中整理报告。即使在高度复杂或繁忙的开发环境中,这也使得通过审计更容易
原理
SAST是基于静态代码分析技术
静态代码分析技术
静态代码分析是指在不实际执行程序的情况下,对代码语义和行为进行分析,由此找出程序中由于错误的编码导致异常的程序语义或未定义的行为。通俗的说,静态代码分析就是在代码编写的同时就能找出代码的编码错误。你不需要等待所有代码编写完毕,也不需要构建运行环境,编写测试用例。
误报原因
误报指的是 SAST 工具报告了一个安全漏洞,但实际上这段代码在真实运行时是安全无害的。
静态代码分析之所以会出现误报,主要原因在于它无法像程序运行时那样拥有完整的上下文信息,只能依赖于对代码结构的推断
- 没有完整的上下文
- 对代码语意的理解不完整
- 函数调用的模型不准确
- 路径可达性问题
解决方案:
1.用户自定义配置: 允许用户配置自定义的净化函数、信任的 Source 或 Sink,以及忽略特定的代码路径
2.基线设置:允许开发者将第一次扫描的结果(通常包含很多误报)审核后设为安全基线,后续只报告新增的或状态发生变化的漏洞
3.结合运行时信息: 某些高级工具(如 IAST)尝试在测试阶段收集运行时信息,然后反馈给静态分析器,以更好地排除虚假路径
4.程序切片:仅分析与污点数据流相关的代码部分,以减少需要处理的复杂性
漏报原因
漏报指的是 SAST 工具未能发现代码中存在的、实际可被利用的安全漏洞
1.对复杂数据流的追踪失败
2.无法处理动态和运行时特性
3.不完整的规则集和模型
4.跨模块跨语言分析限制
解决方案:
1.结合黑盒测试(DAST)
2.结合IAST
3.人工代码审计
词法语法语义
词法
词法分析,将原始的字符流转化为有意义的,离散的单元–>词元(type + Lexeme)
Eg:
1 | if (x >= 0) { ... } |
读取则是按照if,(,x….,if匹配关键词模式,x是字母,匹配标识模式
空格,注释,换行符等无意义的内容将会被剔除
产生的词元(token),eg:x ,则为IDENTIFIER x
语法
语法分析是理解代码的结构。它接收词法分析产生的 Tokens 序列,并检查它们是否符合语言的句法规则
Eg:
1 | Tokens 序列 (if, (, x, >=, 0, ), {, ...) |
验证序列是否满足语法结构内容:
1 | 语言规则规定:IF 语句 = IF 关键词 + ( + 表达式 + ) + 块 |
产出:AST
Eg1:
1 | graph TD |
Eg2:

其AST:

语义
语义分析是理解代码的含义。它在 AST 的基础上进行,确保代码在逻辑上和类型上是正确和有意义的,并为执行或安全分析做准备
1.类型检测
eg:
1 | int = "123" |
这在上述的词法和语法可能会通过,因为它们并不关注代码逻辑,但是在语义上会出错
2.数据流分析
追踪变量的值和状态在程序中的传播路径,多用于污点分析
3.控制流分析
确定程序执行的所有可能路径
产出:Control Flow Graph 和 Data Flow
IR
Intermediate Representation(中间表示)
IR一般由AST经过类型检查和规范化后转换而来
它是源程序在编译器或者静态分析器的内部表示,所有的代码分析,优化和转换工作都是基于中间表示进行的
在现代编译器和静态分析工具中,通常会使用控制流图(Control Flow Graph,CFG)来表示程序的控制流,使用静态单赋值(Static Single Assignment,SSA)来表示程序中数据的使用-定义链(Use-Def Chain),这两个关键数据结构都是AST中没有的
Eg:

其IR:

IR与AST
IR在静态代码分析中比AST的准确性高
原因:
对AST进行类型检查和规范化,即可转换为IR。AST上适合做一些代码规范的检查,例如标识符命名规范检查或常见的编码惯用法检查,AST上的检查一般使用图模式匹配的方法
而IR上能进行更深层次的流敏感分析,过程间分析,上下文敏感分析和对象敏感分析等等,从而实现各种更高难度的程序漏洞检查。相比IR,AST有这些明显的劣势:AST不能很好的表示控制流和数据流,AST做为输入源代码的树状表示,它本身就缺乏表示控制流和控制流的方式。AST是非规范化的,相同语义的结构如果写法不同,它们在AST上的表示也会不同。例如C语言中使用for、while和if/goto表达的循环结构,它们的AST是不一样的;而转换为IR后产生的控制流图是一样的。规范化使得对程序语义的分析更容易,使得检测精确度更高。
IR在静态分析上的优势
着重在于稳定性与通用:
通常AST都是输入语言相关的,比如C程序有对应的C AST,Java程序有对应的Java AST;而IR一般来说是输入语言无关的,不管是C源代码、Java源代码或者其他语言的源代码,它们都能被转换到一个语言无关的IR上。
我们将各种分析和检测引擎放置在IR上,那么相同的分析引擎和检测引擎,搭配不同语言的检测规则,就可以实现对不同语言编码缺陷的检测。使用IR的另一个好处是相对AST,IR会更稳定。
例如现在C++规范每3年就会出一个新标准,引入新的语法结构,意味着AST每3年就会出现新的节点需要处理。如果将分析引擎建立在AST基础上,那么分析引擎也需要每3年更新一次处理这些新节点;而如果将分析引擎建立在IR基础上,则仅需将新的AST节点转换为已有的IR结构或操作,从而保持分析引擎基本不受影响
