URLDNS利用链
我们将ysoserial-all.jar进行导入
ysoserial-all.jar
原理分析
具体的利用点在URL类的hashcode函数中
在java中,hashcode()是Object类中的一个方法,用于返回一个对象的哈希码(hashcode),该哈希码是一个int类型的数值,代表了该对象的特定标识符。哈希码的主要作用是在集合中进行元素的快速查找,比如在HashMap和HashSet中
我们写一个demo
import java.net.MalformedURLException; |
import java.net.URL; |
public class urldns { |
public static void main(String[] args) throws MalformedURLException { |
URL url = new URL("http://rpttv7.dnslog.cn"); |
url.hashCode(); |
} |
} |
其中,域名是我们自己生成的,用于被java访问,这样在DNS服务会有记录
回到顶部
hashcode
去看hashcode方法
可以看到,这里先做了一个判断,然后调用handler的hashcode方法。而handler是URL类中的一个属性
接着进入handler对象
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; |
} |
这个方法传入一个URL类作为参数,依次通过调用getProtocol,getHostAddress,getFile,getPort,getRef等方法获取到传入的URL链接的Protocol(协议),HostAddress(主机地址),File(文件路径),Port(端口),Ref(锚点,即#后面的部分),获取完之后,对每部分调用他们的hashcode方法,将结果加到h上,最后将h返回
不过我们需要重点关注的是getHostAddress方法,该方法会返回一个IP地址,如果遇到的是域名,那么就需要发起DNS请求来将其解析成IP地址
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; |
} |
如果 u.hostAddress 为空,那么调用 URL 类的 getHost 方法获取主机地址(可以是 IP 也可以是域名),如果获取到的主机地址不为空,那么会调用 InetAddress 类的静态方法 getByName 并将主机名作为参数传入。
重点来了:InetAddress.getByName 是一个强大而实用的方法,它允许我们根据主机名获取对应的 IP 地址,并在各种网络应用场景中发挥巨大的作用。
发起请求有了,反序列化在哪里呢?这就要看hashmap类。
回到顶部
HashMap类
作用是用来存储内容,内容以键值对的形式存放。
import java.util.HashMap; |
public class RunoobTest { |
public static void main(String[] args) { |
// 创建 HashMap 对象 Sites |
HashMap<Integer, String> Sites = new HashMap<Integer, String>(); |
// 添加键值对 |
Sites.put(1, "Google"); |
Sites.put(2, "Runoob"); |
Sites.put(3, "Taobao"); |
Sites.put(4, "Zhihu"); |
System.out.println(Sites); |
} |
} |
首先该类继承了Serializable接口,一个类继承该接口可以进行反序列化处理
并且该类还有对数据序列化的writeObject和对数据反序列化的readObject
对于java对象序列化操作的类是ObjectOutputStream,反序列化的类是ObjectInputStream
左键点击ObjectOutputStream类
ObjectOutputStream,它提供了不同的方法用来序列化不同类型的对象,比如writeInt等,对于自定义类型,提供了writeBoolean、writeObject等方法。