Tabby安装配置及使用

Sl0th Lv4

Tabby安装配置及使用

0x00安装

Neo4j Desktop

官网直接下 Neo4j Desktop Download | Free Graph Database Download

下完打开初始化完可以看到数据库版本,下对应版本的APOC插件

image-20230501151304382
image-20230501151304382

新建Neo4j图数据库

image-20230501152338340
image-20230501152338340

可以选择更新数据库版本到5.4.0

image-20230501162942114
image-20230501162942114

打开数据库旁的···->Settings...更改以下配置

1
2
3
4
5
6
7
8
9
#允许从本地任意位置载入csv文件(大概在前面几行)
#server.directories.import=import
#允许 apoc扩展(大概在配置文件末尾部分)
dbms.security.procedures.unrestricted=jwt.security.*,apoc.*
# 修改内存相关配置
# 可以通过官方的neo4j-admin来推荐配置内存大小
dbms.memory.heap.initial_size=1G
dbms.memory.heap.max_size=4G
dbms.memory.pagecache.size=4G

配置 apoc 的配置,需要找到配置文件目录,在这个目录下新建 apoc.conf 文件,内容为

image-20230501161001178
image-20230501161001178

1
2
apoc.import.file.enabled=true
apoc.import.file.use_neo4j_config=false

最后,配置一下 apoc 和 tabby 插件,打开 plugins 目录将对应的 jar 复制到与上面conf同目录下的plugins目录

tabby插件:Releases · wh1t3p1g/tabby · GitHub (在env目录里,同时把env里面几个apoc的jar包都复制到plugins里)

image-20230501163440727
image-20230501163440727

验证配置

重启数据库后,open->Neo4j Browser,测试查询语句,查看一下apoc(有30项)和tabby(有两项)的配置

image-20230501163735244
image-20230501163735244

简单启动

在下载的tabby文件夹中新建一个case目录,下面放目标jar,同时修改config/settings.properties

image-20230501190832777
image-20230501190832777

image-20230501191148762
image-20230501191148762

使用jdk8启动tabby.jar,命令行:

1
java -Xmx6g -jar tabby.jar

可能出现的报错

1
2
3
4
5
6
7
8
9
10
11
java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:771) [spring-boot-2.7.7.jar!/:2.7.7]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:752) [spring-boot-2.7.7.jar!/:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-2.7.7.jar!/:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) [spring-boot-2.7.7.jar!/:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) [spring-boot-2.7.7.jar!/:2.7.7]
at tabby.App.main(App.java:28) [classes!/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_341]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_341]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_341]
....

把config/settings.properties中的tabby.cache.isDockerImportPath设置为false,这个选项用于判断当前是否是docker环境,如果是本机直接使用,要设置成false

图数据库索引配置

可以加快导入/删除的速度,只要在Neo4j browser里运行即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
#之后可以运行下面命令来查看表库和数据库信息
:schema
:sysinfo

0x01简单使用

CC链

以找cc链为例,将tabby目录下的配置文件的tabby.build.target该成commons-collections jar所在位置

image-20230504085113381
image-20230504085113381

shell运行

1
java -Xmx6g -jar tabby.jar

注意要使用java8

成功连接数据库

image-20230504085210709
image-20230504085210709

可能的报错

image-20230504085257308
image-20230504085257308

原因:Neo4j数据库未开启,即使数据库未开启,刚开始的info仍显示有”default”数据库

出现下图即表示导入完毕

image-20230504085512803
image-20230504085512803

查询

打开Neo4j browser,用以下语句查询CC7

1
match path=(m1:Method {SIGNATURE:"<java.util.Hashtable: void readObject(java.io.ObjectInputStream)>"})-[:CALL ]->(m2:Method {NAME:"reconstitutionPut"})-[:CALL ]->(m3:Method {NAME:"equals"})-[:ALIAS*..2]-(m4:Method)-[:CALL ]->(m5:Method {NAME:"get"})-[:ALIAS*1..2]-(m6:Method {NAME:"get"})-[:CALL]->(m7:Method {NAME:"transform"})-[:ALIAS*]-(m8:Method)-[:CALL]->(m9:Method {IS_SINK:true})  return path

可以很明显的看到是从Hashtable的readObject为起点,hashtable反序列化时调用reconstitutionPut方法,在这个方法的执行流程中会调用equals判断key是否重复,如果调用的是AbstractMap的equals,之后会触发LazyMap的get,之后就是常规的触发transform

image-20230504091827921
image-20230504091827921

查询结果节点以id显示,点击后可以在右框查看属性

语法分析

  • Neo4j中有三种指向:() - [] -> ()() <- [] - ()() - [] - ()。顾名思义,前两种就是看箭头方向表示对应的单项关系;最后一种表示双向关系

  • 形如[:CALL]的可以认为给调用边起一个别名CALL

  • 对于每个节点,SIGNATURE属性存储着完整的方法名称

    image-20230504091725958
    image-20230504091725958

  • 上述查询语句中equals方法后为[:ALIAS*..2]

    • *1..N的意思即为:如果在1到N层关系中存在路径,将返回开始点和结束点,若缺省开头,则默认从1开始,所以[:ALIAS*..2]表示找两层以内的方法
  • 在Neo4j查询语句CQL中可以设定指定方向,如-[:CALL ]->,而-[:ALIAS*1..2]-没有指定方向,说明关系内的方法只能作为alias,可以理解为从当前节点向外广度延伸以搜索能调用到下一个方法节点的调用链

  • 每个节点都有两个属性 IS_SINK IS_SOURCE ,分别代表是否是结尾节点和起始节点

根据查询结果很容易发现调用链

image-20230504123909760
image-20230504123909760

0x02CTF中使用

上面找cc链的过程指向性比较强,在ctf中,可以利用该工具找到两个方法之间的调用链

[长城杯 2022]b4bycoffee

题目给出源码,反编译一下,coffeeBean的toString有个字节码后门

image-20230504124900205
image-20230504124900205

反序列化入口,跟进一下AntObjectInputStream

image-20230504125123715
image-20230504125123715

在反序列化时设置了黑名单类,过滤了这些

1
BadAttributeValueExpException,ObjectBean,ToStringBean,TemplatesImpl,Runtime

image-20230504125216104
image-20230504125216104

现在只要触发toString,但是常用的BadAttributeValueExpException被ban了,注意到依赖中存在rome,可以用EqualsBean的hashcode方法可以触发到任意类的toString方法

image-20230504125407054
image-20230504125407054

但是这题也可以用tabby找一个readObject->toString的链子,写出以下查询语句

1
2
3
4
5
match (source:Method {NAME:"readObject",CLASSNAME:"java.util.HashMap"})
match (sink:Method {NAME:"toString"})
with source, collect(sink) as sinks
call tabby.algo.findJavaGadget(source, sinks, 12, false,true) yield path where none(n in nodes(path) where n.CLASSNAME in ["javax.management.BadAttributeValueExpException","com.sun.jmx.snmp.SnmpEngineId","com.sun.xml.internal.ws.api.BindingID","javax.swing.text.html.HTML$UnknownTag"])
return path limit 1

设置起始节点为HashMap的readObject,结束节点为toString方法

之后排除了BadAttributeValueExpException等方法

tabby内的findJavaGadget接口会通过污点传播,根据java原生反序列化的规则来查找利用链,个参数分别表示起始节点、结束节点、路径的最大节点数、isBackward、depthFirst

非常清晰的jdk原生利用链

image-20230504130444449
image-20230504130444449

参考

Java代码分析工具Tabby在CTF中的运用 | CTF导航 (ctfiot.com)

Tabby 源码分析 | m0d9’s blog

Neo4j 第九篇:查询数据(Match) - 悦光阴 - 博客园 (cnblogs.com)

[tabby/Tabby 食用指北.md at master · wh1t3p1g/tabby · GitHub](https://github.com/wh1t3p1g/tabby/blob/master/doc/Tabby 食用指北.md)

  • 标题: Tabby安装配置及使用
  • 作者: Sl0th
  • 创建于 : 2022-12-06 23:29:13
  • 更新于 : 2024-11-11 18:23:06
  • 链接: http://sl0th.top/2022/12/06/Java反序列化工具Tabby使用/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论