3. SAST核心原理与技术分类
SAST(Static Application Security Testing,静态应用安全测试)之所以能在代码尚未运行时就发现漏洞,根本原因在于它把“程序”当作可分析的对象,而不是当作待执行的指令。理解 SAST,关键是理解它用哪些分析技术去逼近“这段代码在什么条件下会出问题”。本节围绕四类核心技术展开:模式匹配、数据流分析、污点追踪与控制流分析,并说明它们各自的适用边界。
一、模式匹配:最快,也最容易被绕过
模式匹配是最直观的静态分析方式:把源码或中间表示与已知的危险模式做比对。例如在 Java 中匹配 Runtime.getRuntime().exec(,在 Python 中匹配 eval(、os.system(,在 JavaScript 中匹配 innerHTML =。它本质上是“正则 + 语法结构”的规则库,实现简单、扫描极快,适合做第一道粗筛。
但模式匹配的边界非常明显。它不理解数据从哪来、到哪去,因此无法区分 exec("ls") 与 exec(userInput);也无法识别经过拼接、编码、变量中转后的危险调用。它还会产生大量误报——只要出现危险函数就报警,而不判断参数是否可控。因此模式匹配适合发现“明显违规写法”,不适合作为漏洞判定的最终依据。
二、数据流分析:追踪值在程序中的传播
数据流分析关注的是“一个值如何从定义点传播到使用点”。它通常在控制流图(CFG)上计算每个程序点的数据流事实,例如到达定值、活跃变量、可用表达式。对安全而言,最有价值的是可达性分析:某个变量是否可能携带外部输入到达敏感操作。
数据流分析比模式匹配精确,因为它能跨语句、跨基本块追踪变量。例如:
String name = request.getParameter("name"); // 定义点:外部输入
String sql = "SELECT * FROM users WHERE name='" + name + "'"; // 传播
stmt.executeQuery(sql); // 使用点:敏感操作
数据流分析可以判断 name 的值是否可能流入 sql,再流入 executeQuery。但它本身不区分“外部输入”和“内部常量”,也不判断是否经过净化。因此数据流分析常作为污点追踪的底层引擎,而不是独立的漏洞判定器。
三、污点追踪:SAST 最核心的漏洞判定技术
污点追踪是数据流分析的安全特化版本。它把变量分为三类:污点源(Source)、传播规则(Propagator)、汇聚点(Sink)。Source 是外部可控输入,如 HTTP 参数、请求头、文件内容、环境变量;Sink 是危险操作,如 SQL 执行、命令执行、文件写入、反序列化;Propagator 描述污点如何随赋值、拼接、函数调用传播。
当一条路径从 Source 出发,经过若干传播后到达 Sink,且中间没有经过有效的净化函数(Sanitizer),就判定为一条污点路径,即潜在漏洞。例如 SQL 注入的判定逻辑是:request.getParameter → 字符串拼接 → executeQuery,中间若没有 PreparedStatement 参数化,则报告。
污点追踪的精度取决于三个配置:Source/Sink 规则库是否覆盖框架、传播规则是否理解字符串拼接与容器操作、Sanitizer 是否被正确识别。它的主要挑战是路径爆炸和跨函数/跨文件传播,因此工程上常配合过程间分析和调用图来限制搜索空间。
四、控制流分析:为路径判断提供骨架
控制流分析构建程序的控制流图,描述语句之间的执行顺序与分支关系。它本身不直接判定漏洞,但为数据流和污点追踪提供“路径是否可达”的基础。例如判断 if (user.isAdmin()) 分支内的危险操作是否可能被普通用户触发,就需要控制流与条件约束分析。
控制流分析还能识别不可达代码、死循环、异常处理路径等。在 SAST 中,它常与过程间分析结合,构建跨函数的调用图,从而支持跨文件污点传播。没有控制流分析,污点追踪只能停留在单个函数内部,无法覆盖真实工程中的多层调用。
五、技术分类与适用边界对照
| 技术 | 核心对象 | 擅长发现 | 主要局限 | 典型工具位置 |
|---|---|---|---|---|
| 模式匹配 | 源码文本/语法树 | 危险函数调用、硬编码密钥 | 误报高、无法判断参数可控性 | 快速规则扫描层 |
| 数据流分析 | 变量定义-使用链 | 值传播路径、未初始化变量 | 不区分内外输入、不判定净化 | 污点追踪底层引擎 |
| 污点追踪 | Source/Sink/Sanitizer | SQL注入、命令注入、XSS | 路径爆炸、跨框架规则依赖 | SAST 核心判定器 |
| 控制流分析 | CFG/调用图 | 路径可达性、跨函数调用 | 不直接判定漏洞 | 路径与调用关系基础 |
六、工程实践中的组合策略
真实 SAST 工具不会只用一种技术,而是分层组合:先用模式匹配做快速粗筛,过滤明显违规;再用控制流分析构建调用图,确定分析范围;最后用污点追踪做精确判定,输出带路径的漏洞报告。以 GitLab SAST 为例,其底层分析器(如 Semgrep、SpotBugs、ESLint 安全插件)各自采用不同技术,最终统一为 GitLab 的漏洞报告格式。
- Source 是否真的外部可控?例如参数是否来自 HTTP 请求而非配置常量。
- 传播路径是否完整?中间是否有变量中转、拼接、编码未被规则覆盖。
- Sanitizer 是否被正确识别?例如是否使用了参数化查询、白名单校验、转义函数。