快捷搜索:  汽车  科技

漏洞检测函数(忆享科技戟星安全实验室)

漏洞检测函数(忆享科技戟星安全实验室)下面就通过分析dnsurl这条链, 来学习挖掘调用链的思路。例如:URL(可以发起dns请求)InvokerTransformer(反射动态代码执行) TemplatesImpl(可以实现任意类加载)1.入口类的readObject 直接调用危险方法 ------基本不可能,一把不会有人会在服务器上重写readObject,而且又危险方法2.入口类参数中包含可控类,该类有危险方法,readObject时调用3.入口类参数中包含可控类,该类又调用其他危险方法,readObject时调用比如类定义为Object 调用equals/hashcode/toString重点:类型相同 同名函数4.构造函数/静态代码块等类加载时隐式执行0x02 调用链条件共同条件:实现Serializable 最好jdk自带相同的类 或者通用包里面存在的类(例如Commons Collections)入口类:sou

漏洞检测函数(忆享科技戟星安全实验室)(1)

戟星安全实验室

忆享科技旗下高端的网络安全攻防服务团队.安服内容包括渗透测试、代码审计、应急响应、漏洞研究、威胁情报、安全运维、攻防演练等

本文约2950字,阅读约需8分钟。

0x00 反序列化有可能产生安全问题的形式

1.入口类的readObject 直接调用危险方法 ------基本不可能,一把不会有人会在服务器上重写readObject,而且又危险方法
2.入口类参数中包含可控类,该类有危险方法,readObject时调用
3.入口类参数中包含可控类,该类又调用其他危险方法,readObject时调用比如类定义为Object 调用equals/hashcode/toString
重点:类型相同 同名函数
4.构造函数/静态代码块等类加载时隐式执行

0x02 调用链条件

共同条件:实现Serializable 最好jdk自带相同的类 或者通用包里面存在的类(例如Commons Collections)入口类:source 重写readObject 调用常见的函数 参数类型宽 例如;Map的实现类HashMap(object object)
调用链:gadget chain 相同名称 相同类型执行类 :sink rce ssrf 写文件等等 最重要

例如:URL(可以发起dns请求)InvokerTransformer(反射动态代码执行) TemplatesImpl(可以实现任意类加载)

下面就通过分析dnsurl这条链, 来学习挖掘调用链的思路。

0x03 dnsurl链是什么,有什么用?

用来测试目标网站是否存在反序列漏洞,用到HashMap这个类的反序列化,目标反序列化后会自动发送dns请求,验证是否存在漏洞。因为HashMap这个jdk自带,并且不受任何java版本限制。

0x04 HashMap分析

这里urldns这条路主要用的是HashMap这个类的反序列化,为什么用这个类呢?


1、可以被序列化 继承了Serializable接口
2、JDK自带,参数类型宽,可以传入任意object HashMap(object object)
3、也重写了readObject

漏洞检测函数(忆享科技戟星安全实验室)(2)

为什么要HashMap要重写readObject?


* 需要保住键值唯一性,所以需要计算键值hashCode 在不同机器上算出来的hashCode值是不一样的
* 查看重写的readObject方法,调用了hash()的方法计算key,hash()方法就是调用key的hashCode()方法,而且这里的key是个任意泛型,所有我们可以传入任意对象。

下面是HashCode.readObject()的片段代码,调用了hash(key)

// 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);

漏洞检测函数(忆享科技戟星安全实验室)(3)

传入的是一个Object对象,但是为什么这么确定key里面有hashCode() 因为老祖宗Object就有这个hashCode自带方法 而且是传入的那个类重写了这个方法,就用重写之后的。

序列化进去的数据循序要和反序列化出来的对象循序对应(知识点)

@SuppressWarnings("unchecked") K key = (K) s.readObject(); @SuppressWarnings("unchecked") V value = (V) s.readObject();

上面的readObject代码为什么是K key = (K) s.readObject(); 出来的是k类型,然后V value = (V) s.readObject(); 出来的V类 让我想起了一个知识点:

因为序列化进去的数据要和反序列化出来的对象对应,为了验证我的想法,查看HashMap的writeObject方法

漏洞检测函数(忆享科技戟星安全实验室)(4)

这里没有什么重要的信息,跟进internalWriteEntries(s)方法,代码很明显就是循环序列化key和value。

所以读出来的时候也是循环读key和value。

漏洞检测函数(忆享科技戟星安全实验室)(5)

那么谁的hashCode()方法可以可以发起dns请求呢?

漏洞检测函数(忆享科技戟星安全实验室)(6)

前面4.1已经分析HashMap类反序列化之后会调用key的hashCode()方法,我没就想,到底谁的hashCode可以发起dns请求呢,或者那个类的hashCode方法调用了危险的函数可以被我没利用呢?

URL这个类里面就满足了这些条件,查看URL类的hashCode()

漏洞检测函数(忆享科技戟星安全实验室)(7)

跟进到URLStreamHandler类的hashCode

漏洞检测函数(忆享科技戟星安全实验室)(8)

跟进getHostAddress方法,获取主机地址的意思,下面是getByName通过域名获取ip地址

漏洞检测函数(忆享科技戟星安全实验室)(9)

跟进getAllByName

漏洞检测函数(忆享科技戟星安全实验室)(10)

一直跟下去到IntetAddress 这里发起了dns请求

漏洞检测函数(忆享科技戟星安全实验室)(11)

0x05 dnsurl链代码编写

序列化代码 其实就这么几行:

URL url = new URL("http://www.dns.com/"); HashMap<URL Integer> hashMap = new HashMap<>(); Class<? extends URL> urlClass = url.getClass(); //用反射改里面的值 Field hashCode = urlClass.getDeclaredField("hashCode"); hashCode.setAccessible(true); hashCode.set(url 11);//默认hashCode未-1,这样在put的时候就会发起dns请求,干扰判断 hashMap.put(url 1); hashCode.set(url -1);//把hashCode设置为-1,反序列化的时候也为-1,才会发起dns请求 new ObjectOutputStream(new FileOutputStream("ser.bin")).writeObject(hashMap);

反序列化代码

new ObjectInputStream(new FileInputStream("ser.bin")).readObject();

代码分析

分析:hashCode.set(url 11); //这里是用反射改hashCode的值

为什么要改hashCode里面的值?

因为默认hashCode为-1,

漏洞检测函数(忆享科技戟星安全实验室)(12)

这样在put的时候就会计算hash发起dns请求,干扰判断,然后put完之后改为-1,好让反序列化的时候触发计算hash促发dns请求。

漏洞检测函数(忆享科技戟星安全实验室)(13)

下面是URL类的代码,如果hashCode为-1则计算hash 否则不计算

漏洞检测函数(忆享科技戟星安全实验室)(14)

END

猜您喜欢: