Java反序列化学习记录

关键词: 漏洞 状态: 进行中

反序列化分享【226安全团队内部周分享内容】

https://www.bilibili.com/video/BV1pt411A7mX

从零开始Weblogic反序列化漏洞

https://www.bilibili.com/video/BV16Z4y1K7Rb

参考与致谢:

https://eviladan0s.github.io/2020/07/30/java-sec-newbee/

https://eviladan0s.github.io/2020/07/31/learn-CommonsCollections1/

JavaEE开发体系MVC

应用程序被划分成模型层model 视图层 view 控制层Controller

Servlet (处理用户请求controller)+ JSP(处理数据显示view ) + JavaBean(负责封装数据model )

  • RMI

RMI调用远程Java对象和方法,能让程序员开发处基于Java的分布式应用,RMI目前使用JRMP进行通信。

  • JRMP

JRMP时专门为Java的远程对象定制的协议

  • JNDI

Java提供目录系统,将服务名称和对象关联,使得开发过程及漏洞利用过程中可以使用名称来访问对象

  • T3协议

Weblogic RMI通信使用T3协议,和Web共用一个端口

利用工具

ysoserial:常见gadget链集合,如Commons Collections

Commons Collections是一个拓展Java标准库的Collection结构的第三方基础库

分析:https://www.anquanke.com/post/id/229108

marshalsec

Java反序列化利用工具,开启RMI、LDAP服务,查询可用GAdget,生成特定Payload


RMI

Java RMI(Remote Method Invocation)即Java远程方法调用,它允许一个 JVM 上的 object 调用另一个 JVM 上 object 方法。

RMI程序通常包括三部分:

RMI Registry,提供注册查询等功能,是一种特殊的Remote Object RMI Server,创建Remote Object,将其注册到RMI Registry RMI Client, 通过name向 RMI Registry获取Remote Object reference (stub),调用其方法

RMI程序示例

一个继承java.rmi.Remote的接口 一个实现此接口的类 一个用来创建Registry的主类,实例化后绑定地址

  • 实现接口,接口继承java.rmi.Remote
package RMItest;

import java.rmi.Remote;

public interface RMIRemote extends Remote {
    public void rmiTest();//声明函数
}
  • 使用上述接口实现:
package RMItest;

public class RMIremoteTest implements RMIRemote{
    @Override
    public void rmiTest() {
        System.out.println("hello");
    }
}
  • 服务端
package RMItest;

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, AlreadyBoundException {
        RMIRemote rmitest = new RMIremoteTest(); //接口需要使用实现的具体类去创建对象
        Registry registry = LocateRegistry.createRegistry(1099);
        registry.bind("rmi://127.0.0.1/test", rmitest);
    }
}
  • 客户端
package RMItest;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client {
    public static void main(String[] args) throws RemoteException, NotBoundException {
        Registry registry = LocateRegistry.getRegistry("127.0.0.1",1099);
        RMIRemote rmi = (RMIRemote) registry.lookup("rmi://127.0.0.1/test");
        rmi.rmiTest();
    }
}

反射

Java-反射-简 中反射介绍

利用反射命令执行


Java反序列化方法

  1. 找序列化入口 source
  2. 调用链 gadget
  3. 出发漏洞的目标方法 sink

触发漏洞的方法

Runtime.exec()方法命令执行

String [] cmd={"cmd","/C","copy exe1 exe2"}; 
Process proc =Runtime.getRuntime().exec(cmd);

Method.invoke() 需要释放的选择方法和参数,反射执行java方法

RMI/JNDI/JRMP引用远程对象,简介实现任意代码执行

Apache Commons Collections基础知识

使用transform方法反射调用任意对象函数

使用transform方法执行命令

import org.apache.commons.collections.functors.InvokerTransformer;

public class test {
    public static void main(String[] args){
        InvokerTransformer myInvoke = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{new String("c:\\windows\\system32\\notepad.exe")});
        myInvoke.transform(Runtime.getRuntime());
    }
}

InvokerTransformer 的构造方法

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
        this.iMethodName = methodName;
        this.iParamTypes = paramTypes;
        this.iArgs = args;
    }

transform方法

public Object transform(Object input) {
        if (input == null) {
            return null;
        } else {
            try {
                Class cls = input.getClass();
                Method method = cls.getMethod(this.iMethodName, this.iParamTypes);
                return method.invoke(input, this.iArgs);
            } catch (NoSuchMethodException var5) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist");
            } catch (IllegalAccessException var6) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed");
            } catch (InvocationTargetException var7) {
                throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var7);
            }
        }
    }
}

CommonsCollections Gadgets1 调用链分析

comments powered by Disqus