FIRE: Combining Multi-Stage Filtering with Taint Analysis for Scalable Recurring Vulnerability Detection
1. 背景
大规模漏洞检测(Vulnerability Detection)
主要方法:
手工(manual inspection), 静态分析(static analysis), 模糊测试(fuzz testing), 符号执行(symbolic execution), 污点分析(taint analysis), 深度学习
克隆漏洞(Clone Vulnerbilities)
背景: 由于代码开源, 很多代码复用就导致了很多克隆漏洞产生
定义: 一个包含漏洞的函数被复用(reuse)了, 这就是克隆漏洞(Clone Vulnerbilities)
这个任务就是基于漏洞的相似度判断是不是有漏洞
2. 问题
- 大规模, 检测难以兼顾准确性和速度
- 克隆漏洞有其特点: 复用前后代码行为很像, 不能用已有的方式来处理
3. 思路
- 大规模
- 可以通过减少检测量解决, 这里用的是过滤,
- 接下来就只要想根据什么来过滤,
- 考虑到了漏洞特征(经验, 人为定义), 词法, 语义(why?后面补充)
- 过滤完了
4. 具体方法
0. 整体架构
1. 过滤: 粒度: 函数
why: 因为背景是检测大规模的项目, 函数太多, 所以要进行过滤来筛选, 至于依据什么来过滤, 且看下面
1. 过滤特征不相似: 布隆过滤器过滤
特征: 容易产生漏洞的操作
举例比如数组越界, 野指针这种, 很多漏洞都来源于这玩意
分为: 关键字, 操作符, 敏感API, 格式化字符串
布隆过滤器
Shuffle Fuzz Bloom Filter
? 这个fsl是自己想的还是在哪找到的
后补(ReDeBug: Finding Unpatched Code Clones in Entire OS Distributions 一个克隆漏洞检测的工作里也是用到了布隆)
普通布隆过滤器只能做到精确的判断Target中的特征确确实实在Vul里面, 但是我们要的是相似, 就是Target中的特征和Vul中的相似, 所以要进行一些改进, 变成这个shuffle fuzz布隆
2. 过滤词法:
第一步过滤完全是特征相似的, 但是词法不一定相似,
Tokenize
把Target函数Tokenize, 弄成token序列, 计算和Vul的Jaccard相似度
Jaccard相似度
J a c c a r d ( A , B ) = ∣ A ∩ B ∣ ∣ A ∪ B ∣ = ∣ A ∩ B ∣ ∣ A ∣ + ∣ B ∣ − ∣ A ∪ B ∣ A , B : = s e t s Jaccard(A, B) = \frac{\mid A \cap B \mid}{\mid A \cup B \mid} = \frac{\mid A \cap B\mid}{|A| + |B| - |A \cup B|} \\ A,\ B := sets Jaccard(A,B)=∣A∪B∣∣A∩B∣=∣A∣+∣B∣−∣A∪B∣∣A∩B∣A, B:=sets
就是看公共的元素多不多
细节: 变量名没有被符号化, 原因: 后续要用到变量名做污点分析
但是不符号化会不会影响到相似度呢, 会不会出现仅因为变量名不同而把可能的漏洞函数排除的漏报情况, 作者说这种情况比较少
3. 过滤Add/Del:
why? 后面补充
F
:
s
e
t
=
T
a
r
g
e
t
F
u
n
c
t
i
o
n
F
v
:
s
e
t
=
V
u
l
n
e
r
b
l
e
F
u
n
c
t
i
o
n
F
p
:
s
e
t
=
P
a
t
c
h
F
u
n
c
t
i
o
n
S
d
e
l
=
F
v
−
F
p
S
a
d
d
=
F
p
−
F
v
F: set =Target Function \\ F_v: set = Vulnerble Function \\ F_p: set= Patch Function \\ S_{del} = F_v - F_p \\ S_{add} = F_p - F_v \\
F:set=TargetFunctionFv:set=VulnerbleFunctionFp:set=PatchFunctionSdel=Fv−FpSadd=Fp−Fv
Sdel就是dff的减号行
Sadd就是diff的加号行
add条件
∀ h ∈ S d e l , h ∈ F \forall \ h \ \in \ S_{del}, \ h\ \in\ F ∀ h ∈ Sdel, h ∈ F
del条件
∀ h ∈ S a d d , h ∉ F \forall \ h \ \in \ S_{add}, \ h \ \notin \ F ∀ h ∈ Sadd, h ∈/ F
大概就是和漏洞更像而不是像补丁
4. 过滤AST
就是把AST弄出来,AST结点弄成集合, 然后算Jaccard相似度
筛选阈值:
S i m ( A S T F , A S T F v ) ≥ T 2 S i m ( A S T F , A S T F v ) ≥ S i m ( A S T F , A S T F p ) T 2 : a p r e d e f i n e d t h r e s h o l d Sim(AST_F, AST_{F_v}) \geq T_2\\ Sim(AST_F, AST_{F_v}) \geq Sim(AST_F, AST_{F_p})\\ T_2: a\ predefined\ threshold Sim(ASTF,ASTFv)≥T2Sim(ASTF,ASTFv)≥Sim(ASTF,ASTFp)T2:a predefined threshold
2. 漏洞检测
1. 污点分析作为特征
把Target, Vul, Patch都做污点分析, 搞个污点路径出来,
source是函数参数, 和所有的标识符的名字
sink是api调用
弄出函数的所有污点路径作为函数的签名, 也就是函数在漏洞语义方面的特征
这个过程是特征提取
2. 嵌入
对每条路径中的语句用CodeBERT向量化
将一条路径的语句向量平均, 得到每条路径的向量表示
3. 相似性漏洞检测
a t a r g e t f u n c t i o n i s v u l n e r a b l e i f C 5 : S i m ( S f , S v ) ≥ S i m ( S f , S p ) S f : = t a r g e t f u n c t i o n S v : = v u l n e r a b l e f u n c t i o n ( d a t a s e t ) S p : = p a t c h f u n c t i o n ( d a t a s e t ) S i m ( A ⃗ , B ⃗ ) = A ⃗ ⋅ B ⃗ ∣ ∣ A ⃗ ∣ ∣ ⋅ ∣ ∣ B ⃗ ∣ ∣ ( c o s i n s i m i l a r i t y ) a\ target\ function\ is\ vulnerable\ if \\ C5: Sim(S_f, S_v) \geq Sim(S_f, S_p) \\ \\ S_f := target\ function \\ S_v := vulnerable\ function(dataset) \\ S_p := patch\ function(dataset) \\ \\ Sim(\vec{A}, \vec{B}) = \frac{\vec{A} \cdot \vec{B}}{||\vec{A}|| \cdot ||\vec{B}||}(cosin \ similarity) a target function is vulnerable ifC5:Sim(Sf,Sv)≥Sim(Sf,Sp)Sf:=target functionSv:=vulnerable function(dataset)Sp:=patch function(dataset)Sim(A,B)=∣∣A∣∣⋅∣∣B∣∣A⋅B(cosin similarity)