HacKerQWQ的博客空间

利用链神器-tabby使用

Word count: 1.5kReading time: 7 min
2022/10/02 Share

tabby项目介绍

项目地址

1
https://github.com/wh1t3p1g/tabby

项目介绍

1
2
3
TABBY是一款针对Java语言的静态代码分析工具。

它使用静态分析框架 Soot 作为语义提取工具,将JAR/WAR/CLASS文件转化为代码属性图。 并使用 Neo4j 图数据库来存储生成的代码属性图CPG。

配置Neo图数据库

  1. 下载安装Neo Desktop

    https://neo4j.com/download/?ref=get-started-dropdown-cta

  2. 新建project,设置密码为password

    image-20221002212531624

  3. 下载apoc插件

    https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/4.2.0.0/apoc-4.2.0.0-all.jar

  4. Neo4j图数据库添加配置项

1
2
3
4
5
6
7
apoc.import.file.enabled=true
apoc.import.file.use_neo4j_config=false

dbms.memory.heap.initial_size=1G
dbms.memory.heap.max_size=4G
dbms.memory.pagecache.size=4G
dbms.security.procedures.unrestricted=jwt.security.*,apoc.*
  1. 将apoc的jar包添加到plugins下

    image-20221002212639601

使用命令查看是否导入成功

1
CALL apoc.help('all')

image-20221002212710099

  1. 数据库优化

添加索引

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE CONSTRAINT c1 IF NOT EXISTS ON (c:Class) ASSERT c.ID IS UNIQUE;
CREATE CONSTRAINT c2 IF NOT EXISTS ON (c:Class) ASSERT c.NAME IS UNIQUE;
CREATE CONSTRAINT c3 IF NOT EXISTS ON (m:Method) ASSERT m.ID IS UNIQUE;
CREATE CONSTRAINT c4 IF NOT EXISTS ON (m:Method) ASSERT 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);
:schema //查看表库
:sysinfo //查看数据库信息

删除索引

1
2
3
4
5
6
7
8
9
10
11
DROP CONSTRAINT c1;
DROP CONSTRAINT c2;
DROP CONSTRAINT c3;
DROP CONSTRAINT c4;
DROP INDEX index1;
DROP INDEX index2;
DROP INDEX index3;
DROP INDEX index4;
DROP INDEX index5;
DROP INDEX index6;
DROP INDEX index7;

tabby进行图数据生成

  1. IDEA生成jar包

    将项目导入IDEA就在libs下自动生成了

    image-20221002212244394

  2. 配置必要配置文件

    • 将config下的settings.properties复制到libs下的config下

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      # build code property graph
      tabby.build.enable = true
      # jdk settings
      tabby.build.isJDKProcess = true
      tabby.build.withAllJDK = false
      tabby.build.excludeJDK = false
      tabby.build.isJDKOnly = false

      # dealing fatjar
      tabby.build.checkFatJar = true

      # default pointed-to analysis
      tabby.build.isFullCallGraphCreate = true

      # targets to analyse
      #tabby.build.target = path/to/target
      tabby.build.target = jars/
      tabby.build.libraries = jars/

      # load to neo4j
      tabby.load.enable = true

      # debug
      tabby.debug.details = true
      tabby.debug.inner.details = true

      将rules下的文件也复制到libs下,最终效果如下

      image-20221002212417766

  3. 用tabby对jar包进行代码属性图生成

    首先将jar包放在jars目录下(jar包可以通过在project structure添加artifacts来生成)

    1
    java -Xmx6g -jar .\tabby-1.1.1.RELEASE.jar

利用链查询

作者样例

利用apoc插件查询

1
2
3
4
match (source:Method {NAME:"execute"})
match (sink:Method {IS_SINK:true, NAME:"getInstance"})<-[:CALL]-(m1:Method)
call apoc.algo.allSimplePaths(m1, source, "<CALL|ALIAS", 20) yield path
return * limit 20
  • 第一行表示选择出所有名为execute的方法

  • 第二行表示选择所有调用(CALL)了被标记为sinkgetInstance方法

  • 第三行使用apoc插件的allSimplePaths进行路径搜索

    1
    call apoc.algo.allSimplePaths(m1, source, "<CALL|ALIAS", 20) yield path 
    • startNode是开始节点
    • endNode是结束节点
    • relationshipTypesAndDirections是关系和指向
    • MaxNodes是最大节点数,可以理解为深度

    这里的意思是,列出最大节点数为20,从source(输入)到sink的调用方法的路径(path)

  • 第四行限制返回路径数量为20

自写样例

这是一个通过doUploadBrithdayCard进行文件上传的漏洞,已知该cms使用servlet进行请求的处理,因此source是doGet或者doPost,写成的neo4j语句如下:

1
2
3
4
MATCH (source:Method) WHERE source.NAME in ["doGet","doPost"]
MATCH (sink:Method{NAME:"doUploadBrithdayCard"})<-[:CALL]-(m1:Method)
CALL apoc.algo.allSimplePaths(m1, source ,"<CALL|ALIAS", 8) yield path
RETURN * limit 20

由于不是反序列化的利用链,所以最大深度只设置了8,成功搜索出利用链

image-20221002213643085

其他样例

样例一:

  • 1.对象实现了java.util.Enumeration接口
  • 2.从该对象的nextElement函数开始,最终能到达一个触发恶意行为的sink函数
  • 3.从nextElement函数开始到sink函数,路径上不能出现前面黑名单涉及的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# match source
match (source:Method {NAME:"nextElement"})
<-[:HAS]-(cls:Class)-[:INTERFACE|EXTENDS*]
->(cls1:Class {NAME:"java.util.Enumeration"})

# match调用source的Method
match (source)-[:CALL]->(m1:Method)

# match sink点为JNDI
match (sink:Method {IS_SINK:true, VUL:"JNDI"})

# 设置路径上的黑名单
call apoc.algo.allSimplePaths(sink, m1, "<CALL|ALIAS", 8) yield path
where none(n in nodes(path) where n.CLASSNAME in ["java.beans.EventHandler","java.lang.ProcessBuilder",
"javax.imageio.ImageIO$ContainsFilter","jdk.nashorn.internal.objects.NativeString",
"com.sun.corba.se.impl.activation.ServerTableEntry",
"com.sun.tools.javac.processing.JavacProcessingEnvironment$NameProcessIterator",
"sun.awt.datatransfer.DataTransferer$IndexOrderComparator","sun.swing.SwingLazyValue",
"com.sun.jndi.toolkit.dir.LazySearchEnumerationImpl","sun.rmi.registry.RegistryImpl_Stub",

"com.sun.jndi.dns.BindingEnumeration","com.sun.jndi.cosnaming.CNBindingEnumeration","com.sun.jndi.toolkit.dir.HierMemDirCtx$FlatBindings","com.sun.jndi.ldap.LdapReferralException"])
return source,path limit 50

样例二:

查询以get开头的无参方法、不超过两次调用、到readObject的链子

1
match path=(m1:Method)-[:CALL*..2]->(m2:Method {NAME:"readObject"}) where m1.NAME =~ "get.*" and m1.PARAMETER_SIZE=0 return path

其他属性

Method的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
"properties": {
"IS_FROM_ABSTRACT_CLASS": false,
"IS_SOURCE": false,
"POLLUTED_POSITION": "[]",
"IS_ABSTRACT": false,
"SIGNATURE": "<fe.document.pof.action.DocTree: void doUploadBrithdayCard(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)>",
"IS_ACTION_CONTAINS_SWAP": false,
"IS_GETTER": false,
"IS_ENDPOINT": false,
"HAS_PARAMETERS": true,
"IS_IGNORE": false,
"MODIFIERS": 1,
"HAS_DEFAULT_CONSTRUCTOR": true,
"IS_PUBLIC": true,
"ID": "86caf40594c7880f54857f557940c64d",
"IS_NETTY_ENDPOINT": false,
"IS_SINK": false,
"PARAMETER_SIZE": 2,
"RETURN_TYPE": "void",
"VUL": "",
"NAME0": "fe.document.pof.action.DocTree.doUploadBrithdayCard",
"CLASSNAME": "fe.document.pof.action.DocTree",
"NAME": "doUploadBrithdayCard",
"IS_CONTAINS_SOURCE": false,
"IS_STATIC": false,
"IS_CONTAINS_OUT_OF_MEM_OPTIONS": false,
"SUB_SIGNATURE": "void doUploadBrithdayCard(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)",
"IS_SERIALIZABLE": false,
"IS_SETTER": false
}

Class属性

1
2
3
4
5
6
7
8
9
10
11
12
13
"properties": {
"HAS_INTERFACES": false,
"IS_STRUTS_ACTION": false,
"HAS_SUPER_CLASS": true,
"HAS_DEFAULT_CONSTRUCTOR": true,
"INTERFACES": "[]",
"IS_INTERFACE": false,
"ID": "d8e1d3c444eee94312797846cdf9fec2",
"IS_ABSTRACT": false,
"IS_SERIALIZABLE": false,
"SUPER_CLASS": "com.sun.xml.internal.bind.v2.runtime.output.Pcdata",
"NAME": "com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"
}

Relationship类型

1
2
3
4
5
ALIAS
CALL
EXTENDS
HAS
INTERFACE
CATALOG
  1. 1. tabby项目介绍
  2. 2. 配置Neo图数据库
  3. 3. tabby进行图数据生成
  4. 4. 利用链查询
    1. 4.1. 作者样例
    2. 4.2. 自写样例
    3. 4.3. 其他样例
    4. 4.4. 其他属性