JAVA安全—反射机制攻击链类对象成员变量方法构造方法
前言
还是JAVA安全,哎,真的讲不完,太多啦。
今天主要是讲一下JAVA中的反射机制,因为反序列化的利用基本都是要用到这个反射机制,还有一些攻击链条的构造,也会用到,所以就讲一下。
什么是反射
Java提供了一套反射API,该API由Class类与java.lang.reflect类库组成。
该类库包含了Field、Method、Constructor等类。
对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。
从官方定义中就能找到其存在的价值,在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可)
参考连接:文章 - JAVA安全基础(二)-- 反射机制 - 先知社区
项目创建
创建一个Java项目,名字叫ReflectDemo。
我这里选择JAVAEE8。
把这几个东西删除掉,因为没啥用。
新建一个类叫User。
先写入以下代码,这里说明一下以下四个为成员变量,分别对应3个不同的属性,公共属性、私有属性、保护属性。
public String name = "wlw";public int age = 20;private String gender = "man";protected String job = "sec";
再写入成员方法,一个为public属性,一个为protected属性。
public void userinfo(String name, int age, String gender, String job) {this.name = name;this.age = age;this.gender = gender;this.job = job;}
protected void users(String name, String gender) {this.name = name;this.gender = gender;System.out.println("user的成员方法"+name);System.out.println("user的成员方法"+gender);}
最后再写入两个构造方法,可以看到方法名字都是User,和我们类的名字一样。
public User(){}public User(String name){System.out.println("my name"+name);}private User(String name,int age){System.out.println(name);System.out.println(age);}
Class对象类获取
OK我们的User类已经写好了,现在来获取它里面的方法。可能有人有疑惑我都知道这个类名叫User为啥还要获取它呢,是这样的,你要对一个类进行操作或者调用,首先必须要获取这个类的类名才行进行下一步,并不是说我们人知道类名就行了,还得让代码知道。
根据全限定类名获取
我们直接Class.forName(“全路径类名”),运行起来成功获取类名。
public static void main(String[] args) throws ClassNotFoundException {Class aClass = Class.forName("com.sf.maven.reflectdemo.User");System.out.println(aClass);}
根据类名获取
第二种是直接类名.class即可获取到类名
Class bClass = User.class;
System.out.println(bClass);
根据对象获取
第三种是对象.getClass()直接获取类名。
User user = new User();
Class aClass1 = user.getClass();
System.out.println(aClass1);
通过类加载器获取
第四种就是我们可以通过类加载器 ClassLoader.getSystemClassLoader().loadClass(“全路径类名”); 来获取类名。
ClassLoader clsload=ClassLoader.getSystemClassLoader();Class aClass2 = clsload.loadClass("com.sf.maven.reflectdemo.User");System.out.println(aClass2);
利用反射获取成员变量
前面我们已经获取到类名了,现在我们利用反射来获取类里面的成员变量。
新建一个类叫GetField,在里面写入我们获取成员变量的方法,先在开头加入我们获取类名的代码才行。
常见的获取成员变量的方法有以下几种。
获取所有公共成员变量
可以看到输出的是我们在User定义的两个public成员变量,name和age。
Field[] fields = aClass.getFields();
for (Field field : fields) {System.out.println(field);}
获取所有成员变量
可以看到三个不同属性的成员变量均获取到。
Field[] fields1 = aClass.getDeclaredFields();
for (Field field : fields1) {System.out.println(field);}
获取单个公共成员变量
可以看到只获取了一个name公共成员变量。
//获取单个公共成员变量Field field2 = aClass.getField("name");System.out.println(field2);
获取任意单个成员变量
可以看到无论是什么属性的成员变量都可以获取到。
//获取单个成员变量Field field3 = aClass.getDeclaredField("gender");System.out.println(field3);
成员变量的值修改和获取
看完获取成员变量了,我们再看一下对成员变量的值进行修改还有获取。
首先创建一个对象也就是获取类名,然后获取age这个公共的成员变量,接着获取user对象的age值,最后输出。
可能这里大家有点不明白,前面开头我们不是已经获取类名了,为啥这里还要获取啊。是这样的,前面获取的类名我们只是为了获取其里面的age成员变量,此时我们的age成员变量已经赋值给field4了,field4.get(user)就是获取user类里面的age值,换句话说后面的是我们要从这个User类里面得到这个age的值,也就是说我们new一个其它的类,只要这个类里面有age的成员变量,也会被获取!!!(讲的有点乱,不对还请指正)
//获取成员变量的值User user = new User();Field field4 = aClass.getField("age");Object a = field4.get(user);System.out.println(a);
接着对User类里面age的值进行修改,通过 field4.set(user,30); 修改user类里面的age值,可以看到输出为30,但是我们并没有去修改user类age成员变量的代码,这就是JAVA反射机制!!!
field4.set(user,30);
Object b = field4.get(user);
System.out.println(b);
利用反射获取构造方法
获取类中的构造方法也是有四种方式。
新建一个类叫GetConstructor,用来专门写获取构造方法的代码,同样记得再开头加上获取类名的代码才行。
获取所有公共构造方法
可以看到获取到了我们前面写好的User(String name) 和 USer() 这两个公共的成员方法。
//获取公共构造方法Constructor[] constructors1 = class1.getConstructors();for (Constructor constructor : constructors1) {System.out.println(constructor);}
获取所有构造方法
可以看到无论是public属性还是private属性的构造方法都被获取到了。
//获取所有构造方法Constructor[] constructors2 = class1.getDeclaredConstructors();for (Constructor constructor : constructors2) {System.out.println(constructor);}
获取单个公共构造方法
这个和获取所有的公共构造方法的代码差不多,只不过是指定了 String 类型的构造方法,前面我们写好的String类型的公共构造方法就只有 User(String name) 所以就返回了这个。
//获取单个公共构造方法Constructor constructor3 = class1.getConstructor(String.class);System.out.println(constructor3);
获取单个私有构造方法
和上一个的差不多,只不过是多了个Declared而已。
//获取单个私有构造方法
Constructor constructor4 = class1.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor4);
对构造方法进行操作
setAccessible(true) 临时开启对私有的访问,newInstance 使用构造方法创建对象,传递参数,允许在运行时通过 Constructor
对象调用类的构造方法。
代码逻辑和上面的成员变量修改差不多,上面是从User类里面找age这个成员变量,这里是从User类里面找到符合的构造方法。可以看到我们的两个参数成功传入到 User(String name,int age) 这个构造方法里面,并且成功调用这个构造方法。
//对构造方法进行操作
Constructor constructor5 = class1.getDeclaredConstructor(String.class, int.class);
//临时开启对私有构造方法的访问
constructor5.setAccessible(true);
User uu = (User) constructor5.newInstance("wlwnb666",30);
System.out.println(uu);
利用反射获取成员方法
获取成员方法的方式也是四种,新建一个类叫GetMethod。
获取包括继承的所有公共成员方法,可以看到输出有很多公共成员方法,这是由于它连JAVA中自带的公共成员方法也一并输出了,并不单单输出我们自己写的。
//获取包括继承的所有公共成员方法Method[] methods1 = class1.getMethods();for (Method method : methods1) {System.out.println(method);}
获取不包括继承的所有成员方法,这里输出了所有我们自己写的成员方法,并没有输出JAVA内置的。
//获取不包括继承的所有成员方法Method[] methods2 = class1.getDeclaredMethods();for (Method method : methods2) {System.out.println(method);}
获取单个成员方法,这个要指定我们获取的成员方法名称为 name ,参数类型也要对应上才行。
//获取单个成员方法
Method method3= class1.getDeclaredMethod("users", String.class, String.class);
System.out.println(method3);
和上面几乎一样。
//获取单个公共成员方法
Method method4= class1.getMethod("userinfo", String.class, int.class, String.class, String.class);
System.out.println(method4);
对成员方法进行调用,对我们前面写好的 user 成语方法进行调用。
//调用成员方法
User user = new User();
Method method5= class1.getDeclaredMethod("users", String.class, String.class);
method5.invoke(user,"wlwnb666","sex");
反序列化链条构造
OK,反射的知识点基本都讲完了,那现在我们来构造以下利用链。
先简单写一个调用计算机的命令执行,这个是调用JAVA中自带的包,我们称之为原生调用。
但是我们想一想,如果是第三方的包,是不是就得要用反射机制来得到命令执行,由于这里我没有引入第三方的包,所以我们就用JAVA自带的包来做一下通过反射实现命令执行的演示,当作是外部的包即可。
首先我们可以看到这个Runtime.getRuntime().exec() 这个命令执行方法是来自 java,lang.Runtime这个类的。
那么我们就先获取类名和所有的公共成员方法,记得这里要把路径写全,不能只写Runtime。
可以看到有很多,找到getRuntime这个方法。
查询一下。
现在我们单独把这个getRuntime 获取出来。
此外我们还需获取exec方法,由于exec 需要传参String类型,所以要加String.class。
Method exec = class1.getMethod("exec", String.class);
整个链条如下,由于exec方法属于实例方法,所以所以 exec. invoke 的第一个参数是 Runtime 实例。
这里可能有人不理解第三第四行代码,一开始我也不是很懂,后来查了一下大致理解了。首先我们要知道什么是实例对象,实例指的是通过某个类(Class)创建出来的具体对象,例如:Use user = new Use() 这样就创建了一个实例。那么回到我们的代码,可以看到 getRuntime 方法返回了 currentRuntime,而currentRuntime 正是开头创建的实例,也就是说getRuntime 方法返回的是一个实例。
那么回到我们构造的链条,Object runtime = method4.invoke(class1); 调用 getRuntime 方法,并且返回一个实例赋值给 runtime ,所以 exec.invoke(runtime, "calc.exe"); 第一个参数是runtime,第二个参数才是命令。
除了上面的说到的链条构造样子,还可以这样子去构造,不过感觉没有第一种简单明了。
// 使用 Class.forName 获取 Runtime 类
Class c1 = Class.forName("java.lang.Runtime");// 获取 Runtime 类的默认构造方法
Constructor m = c1.getDeclaredConstructor();// 设置构造方法为可访问
m.setAccessible(true);// 使用反射调用 Runtime 类的 exec 方法,执行系统命令 "calc"
c1.getMethod("exec", String.class).invoke(m.newInstance(), "calc");
不安全的反射对象
指应用程序使用具有反射功能的外部输入来选择要使用的类或代码,
可能被攻击者利用而输入或选择不正确的类。绕过身份验证或访问控制检查
参考连接:悟空云课堂 | 第七期:不安全的反射漏洞 - 知乎
文章 - JAVA反序列化 - Commons-Collections组件 - 先知社区
相关文章:

JAVA安全—反射机制攻击链类对象成员变量方法构造方法
前言 还是JAVA安全,哎,真的讲不完,太多啦。 今天主要是讲一下JAVA中的反射机制,因为反序列化的利用基本都是要用到这个反射机制,还有一些攻击链条的构造,也会用到,所以就讲一下。 什么是反射…...

专业学习|一文了解并实操自适应大邻域搜索(讲解代码)
一、自适应大邻域搜索概念介绍 自适应大邻域搜索(Adaptive Large Neighborhood Search,ALNS)是一种用于解决组合优化问题的元启发式算法。以下是关于它的详细介绍: -自适应大领域搜索的核心思想是:破坏解、修复解、动…...
9. k8s二进制集群之kube-controller-manager部署
同样在部署主机上创建证书请求文件(为之后的证书生成做准备)根据上面的证书文件创建证书(结果会在当前目录下产生kube-controller-manager证书)创建kube-controller-manager服务配置文件创建kube-controller-manager服务启动文件同步kube-controller-manager证书到对应mast…...
轮转数组-三次逆置
题目 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 void rotate(int* nums, int numsSize, int k){}示例: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] …...

3 卷积神经网络CNN
1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron,可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…...

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>黄金矿工
目录 决策树:代码设计代码: 决策树: 代码设计 代码: class Solution {boolean[][] vis;int ret,m,n;public int getMaximumGold(int[][] grid) {m grid.length;n grid[0].length;vis new boolean[m][n]; for(int i 0; i <…...

java基础1(黑马)
一、初识Java 1.Java背景知识 1)Java是美国SUN公司在1995年推出的一门计算机高级编程语言。 2)Java早期名称为OAK,后来才改为Java。 3)Java之父:詹姆斯高斯林。 4)2009年,SUN公司被Oracle公…...
ES6 对象扩展:对象简写,对象属性 表达式,扩展运算符 ...,Object.assign,Object.is,用法和应用场景
1. 对象属性简写 1.1 基本语法 // 传统写法 const name John; const age 25; const user {name: name,age: age };// ES6 简写语法 const user {name,age };1.2 实际应用场景 // 1. 函数返回对象 function createUser(name, age, email) {return {name,age,email}; }// …...

2025 持续防范 GitHub 投毒,通过 Sharp4SuoExplorer 分析 Visual Studio 隐藏文件
在2024年底的网络安全事件中,某提权工具被发现植入后门,攻击者利用 .suo 文件作为隐蔽的攻击方式。由于 .suo 文件是 Visual Studio 项目的隐藏配置文件,通常不为安全研究人员所关注,因此为攻击者提供了潜在的攻击渠道。 初步调查…...

PCB走线宽度与过流能力参考
我们PCB走线,线宽与允许通过电流的大小是什么样的?几个因素 1、允许的温升:如果能够允许的铜线升高的温度越高,那么允许通过的电流自然也就越高 2、走线的线宽:线越宽 ,导线横截面积越大,电阻…...

电商项目-分布式事务(四)基于消息队列实现分布式事务
基于消息队列实现分布式事务,实现消息最终一致性 如何基于消息队列实现分布式事务? 通过消息队列实现分布式事务的话,可以保证当前数据的最终一致性。实现思路:将大的分布式事务,进行拆分,拆分成若干个小…...

g++ -> make -> cmake(草稿)
1 Windows上安装mingw 2 构建一个 c 项目 3 g 编译 4 make 编译 5 cmake 编译...
JSON常用的工具方法
前言: 在日常开发中,JSON 数据的处理是常见的需求。无论是数据转换、格式化还是与其他格式的互转,掌握一些常用的工具方法可以大大提高开发效率。本文将介绍一些实用的 JSON 操作方法,帮助你快速上手。 JSON常用的工具方法 1.json字符串转换…...
【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信
Kubernetes中Pod间的通信 本系列文章共3篇: 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信(本文介绍)【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信…...

[权限提升] Windows 提权 维持 — 系统错误配置提权 - Trusted Service Paths 提权
关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:Trusted Service Paths 提权原理 Windows 的服务通常都是以 System 权限运行的,所以系统在解析服务的可执行文件路径中的空格的时候也会以 System 权限进行解析&a…...
8. k8s二进制集群之Kubectl部署
创建kubectl证书请求文件生成admin证书文件复制admin证书到指定目录生成kubeconfig配置文件接下来完成kubectl配置文件的角色绑定【扩展】kubectl命令补全操作继续上一篇文章《k8s二进制集群之Kube ApiServer部署》下面介绍一下k8s中的命令行管理工具kubectl。 通过kubectl可以…...

初学 Xvisor 之理解并跑通 Demo
官网:https://www.xhypervisor.org/ quick-start 文档:https://github.com/xvisor/xvisor/blob/master/docs/riscv/riscv64-qemu.txt 零、Xvisor 介绍 下面这部分是 Xvisor 官方的介绍 Xvisor 是一款开源的 Type-1 虚拟机管理程序,旨在提供一…...

深度内容运营与开源AI智能名片2+1链动模式S2B2C商城小程序在打造种草社区中的应用研究
摘要:移动互联网的迅猛发展极大地改变了消费者的购物行为和消费习惯,传统的购物体验已难以满足用户日益增长的个性化需求。在这种背景下,深度内容运营和实时互动成为提升用户购物体验、影响用户购物行为的重要手段。同时,开源AI智…...

RNN/LSTM/GRU 学习笔记
文章目录 RNN/LSTM/GRU一、RNN1、为何引入RNN?2、RNN的基本结构3、各种形式的RNN及其应用4、RNN的缺陷5、如何应对RNN的缺陷?6、BPTT和BP的区别 二、LSTM1、LSTM 简介2、LSTM如何缓解梯度消失与梯度爆炸? 三、GRU四、参考文献 RNN/LSTM/GRU …...
音频录制一般在什么情况下会选择保存为PCM?什么情况会选择保存为WAV?
在音频开发中,选择保存为 PCM 或 WAV 格式取决于具体的应用场景和需求。以下是两种格式的特点以及适用场景的分析: PCM 格式 特点: 原始音频数据: PCM 是未压缩的原始音频数据,没有任何文件头或元数据。数据直接以二进…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
mcts蒙特卡洛模拟树思想
您这个观察非常敏锐,而且在很大程度上是正确的!您已经洞察到了MCTS算法在不同阶段的两种不同行为模式。我们来把这个关系理得更清楚一些,您的理解其实离真相只有一步之遥。 您说的“select是在二次选择的时候起作用”,这个观察非…...

持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...
视觉slam--框架
视觉里程计的框架 传感器 VO--front end VO的缺点 后端--back end 后端对什么数据进行优化 利用什么数据进行优化的 后端是怎么进行优化的 回环检测 建图 建图是指构建地图的过程。 构建的地图是点云地图还是什么信息的地图? 建图并没有一个固定的形式和算法…...

LangChain + LangSmith + DeepSeek 入门实战:构建代码生成助手
本文基于 Jupyter Notebook 实践代码,结合 LangChain、LangSmith 和 DeepSeek 大模型,手把手演示如何构建一个代码生成助手,并实现全流程追踪与优化。 一、环境准备与配置 1. 安装依赖 pip install langchain langchain_openai2. 设置环境变…...