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(); 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(); int mappings = s.readInt(); if (mappings < 0 ) { throw new InvalidObjectException ("Illegal mappings count: " + mappings); } else if (mappings == 0 ) { } 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); SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Map.Entry[].class, cap); @SuppressWarnings({"rawtypes","unchecked"}) Node<K,V>[] tab = (Node<K,V>[])new Node [cap]; table = tab; 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循环
注释:读取键和值,并将映射放在HashMap中
1 putVal(hash(key), key, value, false , false );
这里计算了键名的hash值,跟进
键值不为空,会调用 hashCode,hashCode 初始值为 -1,跟进
Read More
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
题目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 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: { ObjectInputStream ois = new ObjectInputStream (new ByteArrayInputStream (Base64.getDecoder().decode(b64token))); AttackResult var10; label64: { label63: { try { before = System.currentTimeMillis(); Object o = ois.readObject(); 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