当前位置: 首页 > article >正文

Java漏洞原理与实战

一、基本概念

1、序列化与反序列化

(1)序列化:将对象写入IO流中,ObjectOutputStream类的writeobject()方法可以实现序列化

(2)反序列化:从IO流中恢复对象,ObjectinputStream类的readObject()方法用于反序列化

(3)意义:序列化机制允许将实现序列化的Java对象转换为字节序列,这些字节序列可以保存到磁盘上,或通过网络传输,以达到以后恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在

(4)序列化与反序列化是让Java对象脱离Java运行环境的一种手段,可以有效的实现多平台之间的通信、对象持久化储存。主要应用在以下场景:

HTTP:多平台之间的通信,管理等,也可以用于流量带外

RMI:是Java的一组拥护开发分布式应用程序的API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI的传输100%基于反序列化,Java RMI的默认端口是1099端口

JMX:JMX是一套标准的代理和服务,用户可以在任何Java应用程序中使用这些代理和服务实现管理,中间件weblogic的管理页面就是基于JMX开发的,而JBoss则整个系统都基于JMX框架

(5)Java代码审计思路

如果是Java原生类,则需要入口类readObject方法,同时实现了序列化接口,使其可以进行有效的反序列化,此时如果存在DNS解析,或者实现反序列化(利用Runtime对象进行类反射操作)

需要有最终的执行函数(可以执行代码或者命令),比如Runtime.getRuntime().exec,ProcessBuilder().start,getHostAddress,文件读写...等等,这些函数需要自己平常去收集,这样审计起来会更得心应手

2、Java类反射机制

(1) 反射机制的作用:通过Java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件),可以通过另外的方式调用到类的属性和方法,甚至私有属性和方法

(2)反射机制的相关类在java.lang.reflect.*包下面

(3)反射机制的相关类有哪些:Constructor、Field、Method、Class等类

(4)java.lang.Class代表字节码文件,代表整个类

(5)java.lang.reflect.Method代表字节码中的方法字节码,代表类中的方法java.lang.reflect.Constructor代表字节码中的构造方法字节码,代表类中的构造方法java.lang.reflect.Field代表字节码中的属性字节码,代表类中的属性

(6)Java中为什么要使用反射机制,直接创建对象不是更方便?

如果有多个类,每个用户所需求的对象不同,直接创建对象,就要不断的去new一个对象,非常不灵活。而Java反射机制,在运行时确定类型,绑定对象,动态编译最大限度发挥了java的灵活性

(7)获取成员变量

(8)获取并调用方法

(9)获取构造方法

(10)访问私有属性

二、类反射机制实践

package com.woniu.vul;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;class Test{public String name = "蜗牛学苑";public int age = 8;private String addr = "西安";private int price = 10000;public Test() {}public Test(int price){this.price = price;}public int setPrice(int price){System.out.println("新价格为:" + price);return price;}public int getPrice(){return this.price;}private void getAddr(){System.out.println("私有方法:" + addr);}}public class Reflect {public static void main(String[] args) throws Exception {/*Test t = new Test();System.out.println(t.getPrice());Test t1 = new Test(15000);System.out.println(t1.getPrice());System.out.println(t.name);*///使用反射机制实现属性和方法的调用(包括构造方法)//使用Class.forName可以获取到类本身,在JVM中动态加载Test类//Class clazz = Class.forName("com.woniu.vul.Test");//Class clazz = Test.class;//使用new Instance进行实例化//Test t = (Test) clazz.newInstance();//System.out.println(t.getPrice());//Object o = clazz.newInstance();  //实例化动态加载的类,类型必须是Object//        Method m1 = clazz.getMethod("getPrice");
//        int price1 = (int)m1.invoke(o,null);
//        System.out.println(price1);
//
//        Method m2 = clazz.getMethod("setPrice",int.class);
//        int price2 = (int)m2.invoke(o,15000);
//        System.out.println(price2);//调用price私有属性和getAddr私有方法,getFiled只能调用公有属性,getDeclareField才能调私有属性//Field f1 = clazz.getDeclaredField("price");//f1.setAccessible(true);  //设置私有属性可访问//System.out.println(f1.get(o));//getMethod只能调用公有方法,而getDeclareMethod才能嗲用私有方法//Method m1 = clazz.getDeclaredMethod("getAddr");//m1.setAccessible(true);//m1.invoke(o,null);//构造方法如果有参数,怎么办?Class clazz = Class.forName("com.woniu.vul.Test");Constructor c = clazz.getConstructor(int.class);  //获取到一个带参数的构造器Object o = c.newInstance(10); //用构造器去构造一个动态加载的类Method m1 = clazz.getDeclaredMethod("getPrice");int price = (int) m1.invoke(o,null);System.out.println(price);//遍历所有方法或操作Method[] methods = clazz.getDeclaredMethods();for (Method method : methods) {System.out.println(method + "   " + method.getName() + "    " + method.getModifiers());}Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {System.out.println(field + "   " + field.getName() + "    " + field.getModifiers());}}
}

三、序列化与反序列化

序列化的实现代码

package com.woniu.vul;import java.io.*;class Student implements Serializable {public String name = "";public int id = 0;public String phone = "";public Student(){System.out.println("构造方法运行");}public void study(){System.out.println("学生正在学习");}public void sleep(){System.out.println("学生正在休息");}
}public class Unserial {public void serial() throws Exception {Student s = new Student();s.name = "张三";s.id = 12345;s.phone = "188123456786";FileOutputStream fos = new FileOutputStream("./data/student.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(s);}public void unserial() throws Exception {FileInputStream fis = new FileInputStream("./data/student.ser");ObjectInputStream ois = new ObjectInputStream(fis);Student obj =(Student) ois.readObject();System.out.println(obj.name);obj.study();}public static void main(String[] args) throws Exception {Unserial us = new Unserial();//us.serial();us.unserial();}
}

序列化的内容如下:

 然后进行反序列化,切记不要去改我们的序列化内容,不然无法反序列化回去

 我们再补充两个小问题

正常情况下,高亮部分是可以被序列化的,但是如果在这之前加上transient来修饰的话就无法序列化

高亮部分的意思就是定义一个序列化版本的编号,也就是唯一标识

 

这个标识是用来干嘛的

接下来我们看看

我们重新反序列化看看效果

报错信息告诉我们是一个不可用的类

为什么不可用,让我们继续看报错信息

序列化的时候类的ID是前面的那一个,但是反序列的时候类的ID是后面那一个,序列化和反序列化的时候标识号是不一样的,意思就是这个类并不是我们需要反序列化的类

我们将代码中的ID改为其序列化时候原本的ID,那我们就可以完成反序列化的操作了

也就是说这个类在序列化的时候会记录下其类的标识UID

接下来我们看看反序列化产生的机制

首先这个序列化对象一旦有重写的方法,那我们在反序列化的时候会优先调用重写的readObject


 因为我们重写了readObject,所以就会先调用readObject,这就是Java反序列化的起点,也是唯一的起点

也就是说Java反序列化漏洞能够被利用,我们得有一个最基本的前提,就是目标类必须重写readObject方法,只有这样,代码才会被自动调用,否则就没有起点

如果不重写readObject方法的话,就不会发生Java反序列化漏洞

而我们的代码已经重写了readObject方法,所以我们可以对其利用

我们可以直接在重写方法的下面加上终点,也就是攻击者想要达到的效果,有始有终,整个攻击链才算完整

当然我们也可以使用类反射机制的手段去执行命令

因为getRuntime的实例不是纯粹的new出来的,而是通过调用getRuntime这个方法来获取其实例的,然后再通过这个实例去调用exec

加载java.lang.Runtime类

获取Runtime类中的getRuntime方法

调用Runtime方法,获取Runtime类的实例

获取Runtime类中的exec(string)方法

调用exec(String)方法,运行外部命令ifconfig

 运行代码,发现没有报错,说明应该是利用成功了,我不知道为啥不会显示执行ifconfig命令的内容,如果是Windows的话,可以将ifconfig改为calc.exe,大概率会显示出计算器

当然为了执行命令,不仅仅只有Runtime,还有ProcessBuilder

接下来我们看看其反射的调用

根据正常的调用来构造反射

先使用Class.forName这个方法来加载java.lang.ProcessBuilder这个类

然后使用Class对象的getConstructor来获取Processbuilder类的构造函数

接着使用Constructor对象的newInstance方法来创建ProcessBuilder的实例

然后使用Class对象的getMethod方法去获取ProcessBuilder中的start方法

最后使用Method对象的invoke方法去调用start方法

 然后运行,发现报错,是类型出现了错误

 我们先去看看ProcessBuilder的构造方法,它不是严格意义上的String,是String...(可变长的字符串)如果是whoami /user这条命令的话,我们得写到两个字符串里面,在Java中,对于可变长的字符串是将其放入到数组当中去

 然后我们将其修改为String[].class

然后继续运行,然后还是报错说类型不匹配

就是因为我们上面定义的是数组,下面是字符串,所以会报错

所以我们要将下面的类型转换为数组类型就可以了,也就是将其放到数组中就可以了,如下

继续运行,发现还是报错,报错信息还是类型不匹配

 我们去看看newInstace的构造方法,发现还是一个数组,它的类型是数组,数组里面的参数还是一个数组

所以这个cmd的类型要定义成二维数组,二维数组只需加两个{}即可,如下

然后去运行,发现没有报错,但是也没有回显命令的内容,应该是电脑的问题,如果是Windows的话在命令那一块改为calc.exe就可以打开计算器了

 

相关文章:

Java漏洞原理与实战

一、基本概念 1、序列化与反序列化 (1)序列化:将对象写入IO流中,ObjectOutputStream类的writeobject()方法可以实现序列化 (2)反序列化:从IO流中恢复对象,ObjectinputStream类的readObject()方法用于反序列化 (3)意义:序列化机制允许将实现序列化的J…...

第十届团体程序设计天梯赛-上理赛点随笔

2025.4.19来到军工路580号上海理工大学赛点参加cccc 校内环境挺好的,校内氛围也不错;临走前还用晚餐券顺走一袋橘子 再来说说比赛 首先是举办方服务器爆了,导致前10分钟刷不出题,一个多小时还上交不了代码 然后就是我用py总有几…...

考公:数字推理

文章目录 1.真题12 312 530 756 ()-3 3 1 12 17 ()356 342 333 324 ()30 28 27 25 () 2215105 1494 1383 1272 ()2 3 8 21 46 ()4/25 1/4 4/9 1 ()39 416 630 848 ()5 8 11 17 () 10714 21 40 77 () 229 2.数字推理方法2.1 差值法2.2 比值法(乘法关系)2.…...

树莓派超全系列教程文档--(32)config.txt常用音频配置

config.txt常用音频配置 板载模拟音频(3.5mm耳机插孔)audio_pwm_modedisable_audio_ditherenable_audio_ditherpwm_sample_bits HDMI音频 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 板载模拟音频(3.5mm耳机…...

面试专栏-02-MySQL知识点(第二部分)

6、锁 1、分类: 全局锁:锁住数据库中的所有表表级锁:每次操作锁住整张表行级锁:每次操作锁住对应行的数据 2、全局锁 加锁后,整个实例只能进行读取操作,从而保证数据的完成性和一致性。 特点&#xff…...

55、⾸屏加载⽩屏怎么进⾏优化

答: (1)使⽤CDN 减⼩代码体积,加快请求速度; (2)SSR通过服务端把所有数据全部渲染完成再返回给客⼾端; (3) 路由懒加载,当⽤⼾访问的时候,再加载相应模块; (4) 使⽤外…...

python函数之间嵌套使用yield

假设一种场景,函数 A 可以在获得函数 B 的返回值(即一个生成器对象)后,再次对其进行 yield 操作。这是因为 Python 的生成器是可迭代的,你可以在一个生成器中迭代另一个生成器,并将其结果逐个 yield 出去。…...

【MySQL数据库入门到精通】

文章目录 一、SQL分类二、DDL-数据库操作1.查询2.创建数据库3.删除数据库4.使用数据库 三、DDL-表操作1.查询 一、SQL分类 根据功能主要分为DDL DML DQL DCL DDL:Date Definition Language数据定义语言:定义数据库,表和字段 DML:Date Manipulatin Lan…...

[Swift]pod install成功后运行项目报错问题error: Sandbox: bash(84760) deny(1)

操作: platform :ios, 14.0target ZKMKAPP do# Comment the next line if you dont want to use dynamic frameworksuse_frameworks!# Pods for ZKMKAPPpod Moyaend pod install成功后运行报错 报错: error: Sandbox: bash(84760) deny(1) file-writ…...

游戏引擎学习第233天

原地归并排序地方很蒙圈 game_render_group.cpp:注意当前的SortEntries函数是O(n^2),并引入一个提前退出的条件 其实我们不太讨论这些话题,因为我并没有深入研究过计算机科学,所以我也没有太多内容可以分享。但希望在过去几天里…...

卷积神经网络基础(二)

停更好久的卷积神经网络基础知识终于开始更新了哈哈,今天主要介绍的是误差反向传播法。 目录 一、计算图 1.1 用计算图求解 1.2 局部计算 1.3 为什么采用计算图 二、链式法则 2.1 计算图的反向传播 2.2 链式法则 2.3 链式法则和计算图 三、反向传播 3.1 …...

探索大语言模型(LLM):定义、发展、构建与应用

文章目录 引言大规模语言模型的基本概念大规模语言模型的发展历程1. 基础模型阶段(2018年至2021年)2. 能力探索阶段(2019年至2022年)3. 突破发展阶段(以2022年11月ChatGPT的发布为起点) 大规模语言模型的构…...

树莓派超全系列教程文档--(33)树莓派启动选项

树莓派启动选项 启动选项start_file ,fixup_filecmdlinekernelarm_64bitramfsfileramfsaddrinitramfsauto_initramfsdisable_poe_fandisable_splashenable_uartforce_eeprom_reados_prefixotg_mode (仅限Raspberry Pi 4)overlay_prefix配置属…...

PTA:模拟EXCEL排序

Excel可以对一组纪录按任意指定列排序。现请编写程序实现类似功能。 输入格式: 输入的第一行包含两个正整数 n (≤105) 和 c,其中 n 是纪录的条数,c 是指定排序的列号。之后有 n 行,每行包含一条学生纪录。每条学生纪录由学号(6…...

Python 爬虫解决 GBK乱码问题

文章目录 前言爬取初尝试与乱码问题编码知识科普UTF - 8GBKUnicode Python中的编码转换其他编码补充知识GBKGB18030GB2312UTF(UCS Transfer Format)Unicode 总结 前言 在Python爬虫的过程中,我尝试爬取一本小说,遇到GBK乱码问题&a…...

Scala与人工智能:融合多范式编程的AI开发利器

在人工智能(AI)技术飞速发展的今天,编程语言的选择直接影响着算法实现效率与系统可扩展性。Scala,作为一门融合面向对象(OOP)与函数式编程(FP)的多范式语言,凭借其独特的…...

解决echarts饼图label显示不全的问题

解决办法 添加如下配置: labelLayout: {hideOverlap: false},...

JCST 2025年 区块链论文 录用汇总

Conference:Journal of Computer Science and Technology (JCST) CCF level:CCF B Categories:交叉/综合/新兴 Year:2025(截止4.19) JCST 2024年 区块链论文 录用汇总 1 Title: An Understandable Cro…...

不带无线网卡的Linux开发板上网方法

I.MX6ULL通过网线上网 设置WLAN共享修改开发板的IP 在使用I.MX6ULL-MINI开发板学习Linux的时候,有时需要更新或者下载一些资源包,但是开发板本身是不带无线网卡或者WIFI芯片的,尝试使用网口连接笔记本,笔记本通过无线网卡连接WIFI…...

选择排序(简单选择排序、堆排序)

简单选择排序(Selection Sort) 1. 算法思想 它通过多次遍历数组,每次从未排序部分中选择最小(或最大)的元素,将其放到已排序部分的末尾(或开头),直到整个数组有序。 2.…...

velocity模板引擎

文章目录 学习链接一. velocity简介1. velocity简介2. 应用场景3. velocity 组成结构 二. 快速入门1. 需求分析2. 步骤分析3. 代码实现3.1 创建工程3.2 引入坐标3.3 编写模板3.4 输出结果示例1编写模板测试 示例2 4. 运行原理 三. 基础语法3.1 VTL介绍3.2 VTL注释3.2.1 语法3.2…...

word选中所有的表格——宏

Sub 选中所有表格()Dim aTable As TableApplication.ScreenUpdating FalseActiveDocument.DeleteAllEditableRanges wdEditorEveryoneFor Each aTable In ActiveDocument.TablesaTable.Range.Editors.Add wdEditorEveryoneNextActiveDocument.SelectAllEditableRanges wdEdito…...

13.第二阶段x64游戏实战-分析人物等级和升级经验

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:12.第二阶段x64游戏实战-远程调试 效果图: 如下图红框,…...

容器化-Docker-基础

一、Docker 核心概念 1、容器化技术的本质 Docker 是基于 Linux 内核的轻量级容器化技术,通过 Namespace 和 Cgroups 实现资源隔离与限制,将应用及其依赖封装成可移植的容器。与传统虚拟机(需模拟完整硬件层)不同,Docker 容器共享宿主机内核,启动时间以秒级计算,资源占…...

六边形棋盘格(Hexagonal Grids)的坐标

1. 二位坐标转六边形棋盘的方式 1-1这是“波动式”的 这种就是把【方格子坐标】“左右各错开半个格子”做到的 具体来说有如下几种情况 具体到庙算平台上,是很巧妙的用一个4位整数,前两位为x、后两位为y来进行表示 附上计算距离的代码 def get_hex_di…...

SICAR 标准 安全门锁操作箱 按钮和指示灯说明

1、安全门锁操作箱 2、按钮和指示灯说明 一、指示灯说明 红灯: 常亮:表示安全门已解锁;闪烁:表示安全门未复位;熄灭:表示安全门已复位。 黄灯: 常亮:表示处于维修模式。 绿灯&…...

Day10【基于encoder- decoder架构实现新闻文本摘要的提取】

实现新闻文本摘要的提取 1. 概述与背景2.参数配置3.数据准备4.数据加载5.主程序6.预测评估7.生成效果8.总结 1. 概述与背景 新闻摘要生成是自然语言处理(NLP)中的一个重要任务,其目标是自动从长篇的新闻文章中提取出简洁、准确的摘要。近年来…...

【blender小技巧】使用blender的Cats Blender Plugin插件将3D人物模型快速绑定或者修复为标准的人形骨骼

文章目录 前言绑定或者修复人形骨骼1、下载模型2、导入模型到blender中3、删除无用的相机和灯光3、导出模型并在unity中使用 专栏推荐完结 前言 有时候我们下载的3D人物模型,可能不带骨骼信息,或者带一些错乱的骨骼信息。这时候我们就可以使用blender将…...

Linux——firewalld防火墙(笔记)

目录 一:Firewalld防火墙的概述 (1)firewalld简介 (2)firewalld&iptables的关系 (3)firewalld与iptables service的区别 1. ‌规则管理方式‌ 2. ‌默认策略与设计逻辑‌ 3. ‌配置文…...

《分布式软总线赋能老旧设备高效通信》

在数字化转型的浪潮中,分布式软总线技术成为实现设备互联互通的关键力量。然而,当面对大量老旧设备时,其性能受限的现状对分布式软总线提出了严峻挑战。如何在这些性能瓶颈下,让老旧设备实现高效连接与通信,是亟待解决…...