tabby静态分析实践
字数 1467 2025-08-19 12:42:28
Tabby静态分析实践指南
0x01 Tabby测试
1a 工具印象
Tabby是一个基于代码属性图的Java静态分析工具,主要特点包括:
- 支持分析编译后的War包、Jar包等形式
- 工作流程分为两个阶段:
- 代码属性图生成阶段:由tabby.core负责生成带污点信息的代码属性图
- 漏洞发现阶段:使用neo4j扩展tabby path finder查询source-sink语句寻找调用链路
1b 安装和运行
环境准备:
- 下载Neo4j 5.12.0
- 下载apoc-5.12.0-core.jar和apoc-5.12.0-extended.jar
- 下载tabby-path-finder-1.0.jar或1.1版本
配置:
# 允许apoc扩展
dbms.security.procedures.unrestricted=jwt.security.*,apoc.*,tabby.*
启动数据库后执行:
CREATE CONSTRAINT c1 IF NOT EXISTS FOR (c:Class) REQUIRE c.ID IS UNIQUE;
CREATE CONSTRAINT c2 IF NOT EXISTS FOR (c:Class) REQUIRE c.NAME IS UNIQUE;
CREATE CONSTRAINT c3 IF NOT EXISTS FOR (m:Method) REQUIRE m.ID IS UNIQUE;
CREATE CONSTRAINT c4 IF NOT EXISTS FOR (m:Method) REQUIRE m.SIGNATURE IS UNIQUE;
CREATE INDEX index1 IF NOT EXISTS FOR (m:Method) ON (m.NAME);
CREATE INDEX index2 IF NOT EXISTS FOR (m:Method) ON (m.CLASSNAME);
CREATE INDEX index3 IF NOT EXISTS FOR (m:Method) ON (m.NAME, m.CLASSNAME);
CREATE INDEX index4 IF NOT EXISTS FOR (m:Method) ON (m.NAME, m.NAME0);
CREATE INDEX index5 IF NOT EXISTS FOR (m:Method) ON (m.SIGNATURE);
CREATE INDEX index6 IF NOT EXISTS FOR (m:Method) ON (m.NAME0);
CREATE INDEX index7 IF NOT EXISTS FOR (m:Method) ON (m.NAME0, m.CLASSNAME);
运行Tabby:
java -Xmx8g -jar tabby.jar
1c 运行配置
推荐配置config/settings.properties:
tabby.debug.details = true
tabby.build.target = cases/java-sec-code-1.0.0.jar
tabby.build.libraries = libs
tabby.build.mode = web # 或gadget
1d 测试结果
- 254MB Jar包分析:16w classes,耗时极长
- 31MB业务代码:2w+ classes,耗时约7分钟
1e 踩坑记录
- 大Jar包分析需要足够内存:建议至少8G
- 分析时间可能很长,需耐心等待
0x02 图数据库Neo4j
2a 入门介绍
Neo4j属性图模型由节点和关系组成,使用Cypher查询语言。
节点表示:
()- 匿名节点(p:Person)- 带变量和标签的节点(:Technology)- 只有标签的节点(work:Company)- 带变量和标签的节点
关系表示:
[:Likes]- 关系类型-[rel:Is_Friends_With {since: 2018}]->- 带属性和变量的关系
2b 概念指南
属性图基本概念:
- 节点(nodes):表示实体
- 标签(labels):对节点分组
- 关系(relationships):连接节点
- 属性(properties):节点和关系的键值对
2c Cypher指南
基本Cypher操作:
-- 创建节点
CREATE (ee:Person {name: 'Emil', from: 'Sweden', kloutScore: 99})
-- 查找节点
MATCH (ee:Person) WHERE ee.name = 'Emil' RETURN ee;
-- 创建关系和节点
MATCH (ee:Person) CREATE (js:Person), (ee)-[:KNOWS {since: 2001}]->(js)
-- 查询所有Person节点
match (any:Person) return any
2d 查询代码属性图
常用查询:
-- 查看图结构
call db.schema.visualization
-- 获取所有标签
call db.labels
-- 获取所有关系类型
call db.relationshipTypes
-- 获取所有节点属性
match (n) unwind keys(n) as allkeys return distinct allkeys
0x03 Tabby实践
3a 查询方法
基本查询模板:
match (source:Method)
match (sink:Method {IS_SINK:true})
call apoc.algo.allSimplePaths(m1, source, "ALIAS>|CALL>", 12) yield path
return * limit 20
3b 静态分析技术问题
Tabby的污点分析特点:
- 对class/method节点建模
- call edge会添加pollution_positions保存污点信息
- 主要关注method->method的数据流追踪
3c 端点识别
Tabby内置端点识别:
- Struts类型
- Servlet类型
- JSP类型
- 注释类型
查询模板:
match (source:Method {IS_ENDPOINT:true})
with collect(source) as sources
match (sink:Method {IS_SINK: true, VUL:"FILE_WRITE"})
with sources, collect(sink) as sinks
call tabby.algo.findPath(sources, "forward", sinks, 8, false) yield path
where none(n in nodes(path) where n.NAME0 in ["java.io.OutputStream.flush","java.io.Writer.flush", "java.util.Iterator.hasNext", "java.lang.Object.toString", "java.io.ObjectOutputStream.<init>", "java.io.PrintWriter.write"])
return path limit 10
3d 查找危险方法
文件上传漏洞检测:
-- 查找顶层service方法
match (source:Method {NAME:"service", CLASSNAME:"com.sun.jersey.spi.container.servlet.ServletContainer"})
-- 查找FileOutputStream构造方法
match (sink:Method {SIGNATURE:"<java.io.FileOutputStream: void <init>(java.lang.String)>",CLASSNAME:"java.io.FileOutputStream"})
-- 查找调用路径
call tabby.algo.findPath(source, ">", sink, 15, false) YIELD path
return path
请求输入流检测:
MATCH path=(source:Method)-[:CALL]->(sink:Method {NAME:"getInputStream"})
where source.CLASSNAME starts with "com.esafenet.servlet"
return path
0x04 实践小结
4a 数据流分析对象
Tabby 1.2版本分析特点:
- 以class、method作为图节点建模
- 节点关系类型:
- class->class: Interface、Extends
- class->method: Has
- method->method: Call、Alias
4b 整体感知
优势:
- 基于Soot生成的字节码分析,支持Jar、classes等文件
- 对反序列化等有明确触发点方法的漏洞检测效果好
- 在查找特定类、Controller/Servlet及其方法方面有优势
劣势:
- 污点流(taint flow)信息较少
- 默认全量分析,难以对大Jar包进行选择性分析
- 数据流调试资料较少
理想污点分析:
- 标记request对象中所有外部可控的数据流
- 追踪这些数据流是否经过指定的危险函数
- 减少底层方法追踪,关注如new FileOutputStream(path)等高层次方法