java中反序列化学习-反射部分
文章介绍了反序列化与反射机制的关系,详细讲解了反射的定义、常用函数(如`forName`和`getMethod`)及其在安全研究中的应用。通过实例展示了如何利用反射绕过沙盒限制,并强调了静态初始化块在恶意代码执行中的作用。 2025-12-13 09:53:0 Author: www.freebuf.com(查看原文) 阅读量:1 收藏

freeBuf

主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

反序列化初识02-反射

一、什么是反射?

一段代码,改变其中的变量量,将会导致这段代码产⽣生功能性的变化,我称之为动态特性。

比如说

public void execute(String className, String methodName) throws Exception {
	Class clazz = Class.forName(className);
	clazz.getMethod(methodName).invoke(clazz.newInstance());
}

在你不知道传入的参数值的时候,你是不知道他的作⽤是干什么的

在安全研究中,我们使⽤用反射的⼀⼤⽬的,就是绕过某些沙盒。比如,上下文中如果只有Integer类型的数字,我们如何获取到可以执行命令的Runtime类呢?也许可以这样:

1.getClass().forName("java.lang.Runtime")

二、反射常用函数

1.forName

Class.forName如果你知道某个类的名字,想获取到这个类,就可以使⽤用forName来获取。

forname方法有多个方法重载,根据参数可分为

Class<?> forName(String name)
Class<?> forName(String name, boolean initialize, ClassLoader loader)
第一个实现等价于`Class.forName(className, true, currentClassLoader);`
  • 参数说明:

    • name:类名,如"java.lang.Integer"

    • initialize:

      • true:加载 + 链接 + 初始化(执行 static 块)

      • false:只加载,不执行 static 块

    • loader:指定类加载器

​ 类加载 ≠ 创建对象;只有创建对象才会调用构造方法,此时未调用构造方法。

  • 类的三种初始化方式

    public class TrainPrint {
        {                               // ① 实例初始化块(Instance Initializer Block)
            System.out.printf("Empty block initial %s\n", this.getClass());
        }
    
        static {                        // ② 静态初始化块(Static Initializer Block)
            System.out.printf("Static initial %s\n", TrainPrint.class);
        }
    
        public TrainPrint() {           // ③ 构造方法(Constructor)
            System.out.printf("Initial %s\n", this.getClass());
        }
    }
    

    使用forname只会调用static即静态初始化块,其在类被加载(初始化)时执行

    因此可以在恶意类中static加入恶意代码,从而执行

    例如:
    import java.lang.Runtime;
    import java.lang.Process;
    public class TouchFile {
        static {
            try {
                Runtime rt = Runtime.getRuntime();
                String[] commands = {"touch", "/tmp/success"};
                Process pc = rt.exec(commands);
                pc.waitFor();
            } catch (Exception e) {
                // do nothing
            }
        }
    }
    
  • 实现沙箱绕过

    1.getClass().forName("java.lang.Runtime")详解

    本质就是class类中有静态方法forname,所以先通过getClass获取integer类对象,进而获取Runtime对象

​ 在SPEL注入中常遇到

  • 内部类加载

    静态内部类不依赖外部类实例,可以直接通过Class.forName

    Class<?> clazz = Class.forName("C1$C2");        //加载类
    Object obj = clazz.getDeclaredConstructor().newInstance();     //c
    

2.getMethodinvoke

getMethod的作用是通过反射获取一个类的某个特定的公有方法。

参数为方法参数列表类,Method m = cls.getMethod("

免责声明

1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。

2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。

3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。

已在FreeBuf发表 0 篇文章

本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)


文章来源: https://www.freebuf.com/articles/web/461881.html
如有侵权请联系:admin#unsafe.sh