Java漏洞原理与实战

news2025/4/20 23:46:49

一、基本概念

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就可以打开计算器了

 

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

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

相关文章

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

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

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

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

【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配置属…

Python 爬虫解决 GBK乱码问题

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

解决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…

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

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

六边形棋盘格(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. ‌配置文…