碎碎念
本文作为笔者学习安全静态分析的第一篇文章,后续会继续更新具体的污点分析、数据流分析、控制流分析等细节、比较好的开源项目实战分析,以及介绍在DevSecOps中的具体落地。
一句话描述
通过分析源代码的结构、语法和语义,以及使用静态分析工具,来检测代码中的错误、漏洞、安全风险和潜在问题的过程
基础术语
词法(Lexical)
指的是将源代码分解成基本的词法单元或记号(Tokens)的过程;词法分析器(Lexical Analyzer)或词法扫描器(Lexer)负责执行词法分析的任务。
语法
用于将源代码转换为抽象语法树(Abstract Syntax Tree,AST)或其他中间表示形式,以便进一步分析
语义
对源代码进行分析,以捕捉其含义、语义和语言规则,并检测可能存在的错误、不一致性和潜在问题
抽象语义树(AST)
在编程语言处理和静态分析中常用的一种数据结构,通过树形结构的方式展示代码的组织和语法关系
中间代码IR
在编译器或解释器中使用的一种中间形式的代码表示。它是源代码经过语法分析和语义分析后的一个抽象表示,能够更方便地进行优化、转换和生成目标代码,不依赖于特定的硬件平台或编程语言,具有相对独立和通用的特性,使得编译器或解释器可以更容易地进行优化和跨平台的支持。
三地址码
用于表示计算机程序的中间代码形式之一,每条指令最多只有三个操作数,通常是两个操作数进行运算,并将结果存储到第三个操作数中
每条指令包含三个字段:操作符(operator)、操作数1(operand1)和操作数2(operand2),并将计算结果存储到操作数3(result)中
t1 = a+b
t2 = t1 * c
d = t2 - a
静态单赋值SSA
中间代码形式之一,每个变量在程序中只被赋值一次,新变量的名称通常是原变量名称加上一个唯一的标识符,方便进行数据流分析、优化和代码生成。
x1 = 1
y1 = x1 + 2
x2 = 3
z1 = x2 * y1
数据流图(DFG)
用于描述程序中的数据流动和数据依赖关系
节点表示程序中的操作或计算,例如变量的定义、赋值、运算等。边表示数据的传递,即数据流动的路径。每个边都有一个方向,表示数据的流向
用于如常量传播、复写传播、活跃变量分析等分析
控制流图 (CFG)
用于描述程序中的控制流程,即程序的执行顺序和条件分支
节点表示程序中的基本块(Basic Block),每个基本块包含一系列顺序执行的语句。边表示控制流的转移,即程序在不同基本块之间的跳转关系。每个边都有一个条件,表示执行跳转的条件。
用于如执行路径、条件分支和循环结构等分析
基本块(Basic Block)
指在程序中一段连续的代码,其中只有一个入口点和一个出口点
调用图(Call Graph, CG)
用于分析和理解程序的函数调用流程
节点表示函数,边表示函数之间的调用关系
用于了解程序中函数之间的直接或间接调用关系、追踪函数的调用路径,了解程序的执行流程、分析函数之间的依赖关系
程序依赖图(Program Dependence Graph, PDG)
用于分析程序的数据流和控制流之间的依赖关系
节点表示程序中的一条语句,而边表示语句之间的依赖关系
系统依赖图(System Dependence Graph, SDG)
用于描述系统中各个组件之间的依赖关系,包括软件组件、硬件设备、网络连接、数据库等
节点表示系统中的一个组件,而边表示组件之间的依赖关系
代码属性图(Code Property Graph, CPG)
源代码中间表示形式, 是当前源代码漏洞 静态分析技术中最新、使用最为广泛的源代码图形 表示, 由 AST、CFG 和 PDG 合并而成
分析方式
污点分析
追踪敏感数据在程序中的传播和使用情况,以检测潜在的数据泄露、注入攻击或安全漏洞
抽象成一个三元组
<sources,sinks,sanitizers>
的形式,其中,source
即污点源,代表直接引入不受信任的数据或者机密数据到系统中;sink
即污点汇聚点,代表直接产生安全敏感操作(违反数据完整性)或者泄露隐私数据到外界(违反数据保密性);sanitizer
即无害处理,代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害.污点分析就是分析程序中由污点源引入的数据是否能够不经无害处理,而直接传播到污点汇聚点.如果不能,说明系统是信息流安全的;否则,说明系统产生了隐私数据泄露或危险数据操作等安全问题.污点分析简化处理过程
显式流分析
分析污点标记如何随程序中变量之间的数据依赖关系传播
隐式流分析
分析污点标记如何随程序中变量之间的控制依赖关系传播
无害处理
污点数据经过该模块的处理后,数据本身不再携带敏感信息或者针对该数据的操作不会再对系统产生危害
例如输入验证 (input validation) 模块应当被识别成无害处理模块,XSS Auditor、CSRF Protect等等
符号执行
用于自动化地探索程序的所有可能执行路径,用符号值(Symbolic Value)替代程序中的具体输入值,然后通过约束求解器来解析这些符号值,生成满足程序约束条件的输入值,从而执行不同的程序路径
简单概括:每次分析到达某预设点的所有路径中输入点的可能值
关键概念和步骤
符号化输入:将程序中的输入值替换为符号值,每个符号值代表一类可能的具体值。例如,用符号变量x代替具体的输入值。
符号执行路径:通过符号值进行路径探索,根据程序中的条件语句(如if语句、循环条件)确定不同的执行路径。
约束条件生成:在符号执行的过程中,收集路径上的约束条件,这些约束条件描述了程序路径中的约束关系。例如,if语句的条件就是一个约束条件。
约束求解:使用约束求解器(Constraint Solver)对收集到的约束条件进行求解,得到满足约束条件的具体输入值。
路径覆盖和错误检测:通过符号执行探索多个路径,覆盖不同的程序执行情况,帮助发现潜在的错误和漏洞。例如,如果在某个路径上发现了不可达的代码或错误条件,就可能存在程序错误。
符号执行过程
指针分析
用于推断程序中指针变量的指向关系,即确定指针变量可能指向的对象或地址
帮助检测潜在的内存安全问题,如空指针解引用、野指针引用等
分析术语
过程间分析(inter-procedure analysis)
用于分析程序中的跨函数或跨过程的行为和属性。它能够跟踪函数之间的调用关系,将信息从一个函数传递到另一个函数,并对整个程序的行为进行综合分析
过程内分析(intraprocedure analysis)
用于在单个函数或过程内分析程序的行为和属性。它关注函数内部的数据流、控制流和语义结构,以便识别函数内部的错误、漏洞和潜在问题
上下文敏感(context-sensitive)
对不同调用位置调用的同一函数加以区分,根据程序的具体上下文环境来推断程序行为和属性,以便更准确地分析和理解程序的语义和行为
上下文不敏感(context-insensitive)
将每个调用或返回看做一个 “goto” 操作,忽略调用位置和函数参数取值等函数调用的相关信息,用于快速检测潜在的安全漏洞,并进行初步的风险评估
流不敏感分析
不考虑语句的先后顺序,按照程序语句的物理位置从上往下顺序分析每一语句,忽略程序中存在的分支
流敏感分析
考虑程序语句可能的执行顺序,通常需要利用程序的控制流图(CFG)
静态分析流程
传统基本流程
基于学习算法的分析流程
基础扫描原理
参考文献
http://jcs.iie.ac.cn/xxaqxb/ch/reader/view_abstract.aspx?file_no=20220408&flag=1
http://jcs.iie.ac.cn/xxaqxb/ch/reader/view_abstract.aspx?file_no=20200510&flag=1
https://xiongyingfei.github.io/SA/2020/main.htm
https://www.jos.org.cn/html/2017/4/5190.htm
https://www.jsjkx.com/CN/article/openArticlePDF.jsp?id=11355
https://www.anquanke.com/post/id/157928
https://www.freebuf.com/articles/ics-articles/362885.html
https://firmianay.gitbook.io/ctf-all-in-one/5_advanced/5.3_symbolic_execution