Notes Site.
post @ 2023-11-11

URLDNS

触发反序列化的方法是readObject,直奔 HashMap 类的 readObject ⽅法

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
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {

ObjectInputStream.GetField fields = s.readFields();

// Read loadFactor (ignore threshold)
float lf = fields.get("loadFactor", 0.75f);
if (lf <= 0 || Float.isNaN(lf))
throw new InvalidObjectException("Illegal load factor: " + lf);

lf = Math.min(Math.max(0.25f, lf), 4.0f);
HashMap.UnsafeHolder.putLoadFactor(this, lf);

reinitialize();

s.readInt(); // Read and ignore number of buckets
int mappings = s.readInt(); // Read number of mappings (size)
if (mappings < 0) {
throw new InvalidObjectException("Illegal mappings count: " + mappings);
} else if (mappings == 0) {
// use defaults
} else if (mappings > 0) {
float fc = (float)mappings / lf + 1.0f;
int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
DEFAULT_INITIAL_CAPACITY :
(fc >= MAXIMUM_CAPACITY) ?
MAXIMUM_CAPACITY :
tableSizeFor((int)fc));
float ft = (float)cap * lf;
threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
(int)ft : Integer.MAX_VALUE);

// Check Map.Entry[].class since it's the nearest public type to
// what we're actually creating.
SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, cap);
@SuppressWarnings({"rawtypes","unchecked"})
Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
table = tab;

// Read the keys and values, and put the mappings in the HashMap
for (int i = 0; i < mappings; i++) {
@SuppressWarnings("unchecked")
K key = (K) s.readObject();
@SuppressWarnings("unchecked")
V value = (V) s.readObject();
putVal(hash(key), key, value, false, false);
}
}
}

最后一段for循环

image-20231113120658086

注释:读取键和值,并将映射放在HashMap中

1
putVal(hash(key), key, value, false, false);

这里计算了键名的hash值,跟进

image-20231113121133713

键值不为空,会调用 hashCode,hashCode 初始值为 -1,跟进

Read More
post @ 2023-11-10

Java反序列化-WebGoat

源项目:webgoat-server-8.2.2(https://github.com/WebGoat/WebGoat/releases)

Jdk:>=15(11不行)

启动命令:

1
java -jar webgoat-server-8.2.2.jar

http://127.0.0.1:8080/WebGoat/login

image-20231112185914293

题目java文件:webgoat-server-8.2.2.jar 解包,webgoat-server-8.2.2/BOOT-INF/lib/insecure-deserialization-8.2.2.jar再次解包,org/org.owasp.webgoat.deserialization下的文件

分析源码

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// InsecureDeserializationTask
package org.owasp.webgoat.deserialization;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.util.Base64;
import org.dummy.insecure.framework.VulnerableTaskHolder;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@AssignmentHints({"insecure-deserialization.hints.1", "insecure-deserialization.hints.2", "insecure-deserialization.hints.3"})
public class InsecureDeserializationTask extends AssignmentEndpoint {
public InsecureDeserializationTask() {
}

@PostMapping({"/InsecureDeserialization/task"})
@ResponseBody
public AttackResult completed(@RequestParam String token) throws IOException {
String b64token = token.replace('-', '+').replace('_', '/');

long before;
long after;
try {
label71: {
// base64解码,通过字节流反序列化对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(b64token)));

AttackResult var10;
label64: {
label63: {
try {
before = System.currentTimeMillis();
Object o = ois.readObject();
// 类必须是VulnerableTaskHolder
if (!(o instanceof VulnerableTaskHolder)) {
if (o instanceof String) {
var10 = this.failed(this).feedback("insecure-deserialization.stringobject").build();
break label64;
}

var10 = this.failed(this).feedback("insecure-deserialization.wrongobject").build();
break label63;
}

after = System.currentTimeMillis();
} catch (Throwable var12) {
try {
ois.close();
} catch (Throwable var11) {
var12.addSuppressed(var11);
}

throw var12;
}

ois.close();
break label71;
}

ois.close();
return var10;
}

ois.close();
return var10;
}
} catch (InvalidClassException var13) {
return this.failed(this).feedback("insecure-deserialization.invalidversion").build();
} catch (IllegalArgumentException var14) {
return this.failed(this).feedback("insecure-deserialization.expired").build();
} catch (Exception var15) {
return this.failed(this).feedback("insecure-deserialization.invalidversion").build();
}

int delay = (int)(after - before);
if (delay > 7000) {
return this.failed(this).build();
} else {
return delay < 3000 ? this.failed(this).build() : this.success(this).build();
}
}
}

Read More
⬆︎TOP