Java反序列化JDK动态代理的关系

Java代理模式

为什么要学习代理模式?了解开发原理,才能明白漏洞的产生。这不仅仅是SpringAOP的底层!
[SpringAOP 和 SpringMVC]
代理模式的分类:

  • 静态代理
  • 动态代理

image.png

静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真是角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人

代码步骤

接口

Rent.java

package Spring_Proxy.Demo01;

//租房的接口
public interface Rent {
    public void rent();
}
真实角色

Host.java

  • 这是一个类,这个类就是房东,做为房东,他需要租房的接口,也就是Rent.java
package Spring_Proxy.Demo01;

//房东
public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }
}

代理角色

Proxy.java:这是一个类,这个类是中介,也就是代理,他需要有房东的房源,这里将房东类作为一个私有属性host,使用host.rent()来实现房东类的rent租房方法

package Spring_Proxy.Demo01;

public class Proxy implements Rent{
    //房东的事情
    private Host host;

    public Proxy() {
    }

    public Proxy(Host host) {
        this.host = host;
    }

//代理的事情
    @Override
    public void rent() {
        host.rent();
        seeHouse();
        hetong();
        fare();
    }

    //看房
    public void seeHouse(){
        System.out.println("中介带你看房");
    }

    public void hetong(){
        System.out.println("签租凭合同");
    }

    //收中介费
    public void fare(){
        System.out.println("收中介费");
    }


}

客户端访问代理角色

Client.java

  • 这是一个启动类,因为这里有main方法,这个类就是租客,租客需要先去找中介,然后才能租房,不能直接找房东是因为房东不想那么麻烦。
package Spring_Proxy.Demo01;

public class Client {
    public static void main(String[] args) {
        //房东要租房子
        Host host = new Host();
        //代理,中介帮房东租房子,但是呢?代理角色一般会有一些附属操作!
        Proxy proxy = new Proxy(host);

        //你不用面对房东,直接找中介租房即可!
        proxy.rent();
    }
}

可以看见运行代码之后,都是代理的操作
image.png

案例演示

比如我们想做一个业务类的功能代码,需要增删改查,后面突然新增了一个功能,是需要日志的,记录增删改查的信息。那么我们肯定是不能再原来的业务代码进行修改了,因为不精简,不眼睛

定义接口代码
  • 这里定义了四个抽象方法
package Spring_Proxy.Demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

实现接口类代码
  • 这里使用一个实现接口类来完成增删改查的操作
package Spring_Proxy.Demo02;

//实现接口类
public class UserServiceimpl implements UserService{


    @Override
    public void add() {
        System.out.println("增加了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }

    @Override
    public void query() {
        System.out.println("查询一个用户");
    }

    //为什么不直接改实现类的代码?
    //1.改动原有的业务代码,在公司中是大忌,如果代码崩了呢?
    //2.业务是业务的方法,我们想添加其他的方法,我们用日志的方法

}

接口类代理代码
  • 这里我们想实现一个新功能,每一次的操作都会有日志记录
  • 我们要在接口代理的代码中实现,这是因为横向开发的原因,不能改变缘来实现接口业务的代码的完整性
  • 缺点就是很麻烦,每一个方法都要添加log()
package Spring_Proxy.Demo02;

public class UserSerivceProxy implements UserService {
    private UserServiceimpl userserivce;

    public void setUserserivce(UserServiceimpl userserivce) {
        this.userserivce = userserivce;
    }

    @Override
    public void add() {
        log("add");
        userserivce.add();
    }

    @Override
    public void delete() {
        log("delete");
        userserivce.delete();

    }

    @Override
    public void update() {
        log("update");
        userserivce.update();
    }

    @Override
    public void query() {
        log("query");
        userserivce.query();
    }

    //日志方法
    public void log(String msg){
        System.out.println("[Debug] 使用了"+msg+"方法");
    }
}

启动类代码
  • 启动类代码,这里有main方法
  • 我们需要实现接口类代码,所以new实现接口类的一个对象
  • 然后后面new了一个代理类的对象
  • 最好使用代理类里面的方法
package Spring_Proxy.Demo02;

public class Client {
    public static void main(String[] args) {
        
        //代理类的一个对象 proxy
        UserSerivceProxy proxy = new UserSerivceProxy();
        //使用代理实现查询功能
        proxy.query();
    }
}

运行代码后可以发现,成功显示了
image.png

静态代理模式的好与坏

代理模式流程如图:讲究的是横向开发
image.png
好处:

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生一个代理角色;代码会翻倍开发效率会变低

动态代理

动态代理的了解

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理、基于类的动态代理
    • 基于接口—JDK 动态代理【我们在这里使用】
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:

  • Proxy:提供了创建动态代理类和实例的静态方法,
  • InvocationHandler:调用处理程序实现的接口
为什么需要动态代理

因为静态代理,如果需要添加什么方法,一个个的很麻烦,动态代理的本质就是利用了反射机制。动态代理能够灵活轻松的减少代码量

代码的实现

动态代理类代码

这是一个万能的动态代理类,固定的写法,我们只需要知道:

  • 有被代理的接口
  • 生成得到的代理类
  • 处理代理示例,并返回结果
  • 总的来说就是我们需要替换target变量就好了
  • 处理代理示例的时候,method方法invoke触发调用的是我们的变量target,args是固定的参数
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


//等我们会用这个类,自动生成代理类!
public class ProxyInvocatioinHandler implements InvocationHandler{

    //被代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
        //这里最后面的this,指的是InvocationHandler
    }


    @Override
    //处理代理示例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //log("add"); 太笨了这个方法
        log(method.getName());
        //动态代理的本质,就是使用反射机制实现!
        Object result = method.invoke(target, args);
        return result;
    }

    //日志方法需求(业务需求)
    public void log(String msg){
        System.out.println("[Debug]执行力"+msg+"方法");
    }
}
  • 可以发现不用重复添加log()
接口启动类代码
  • new一个接口实现类的对象 usersrrvice
  • 然后new一个动态代理类的对象 pih
  • 设置代理的对象为 代码实现类 usersrrvice
  • 最后动态生成这个代理类,使用强制类型转换 为 proxy变量
package Spring_Proxy.Demo04;

import Spring_Proxy.Demo02.UserService;
import Spring_Proxy.Demo02.UserServiceimpl;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceimpl usersrrvice = new UserServiceimpl();
        //代理角色,不存在
        ProxyInvocatioinHandler pih = new ProxyInvocatioinHandler();

        //设置要代理的对象
        pih.setTarget(usersrrvice); 
        //动态生成的代理类
        UserService proxy = (UserService) pih.getProxy();

        proxy.add();
        proxy.delete();

    }
}

运行之后可以看见自动日志方法成功了,这就是动态代理,不需要静态代理的手动重复添加,增加代码量
image.png

动态代理的好处

  • 可以使真实角色的操作更加纯粹!不用去关注一些公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要实现了同一个接口即可

反序列化中动态代理的应用

我们知道反序列化漏洞,需要的是一个入口类。

  • 假设存在一个能够利用的类 为 B.f ,比如Runtime.exec
  • 入口类为 A,最理想情况下是 A[O] -> o.f,那么我们传进去的参数 O 替换为 B即可,但是实际情况下很少

实际情况下:

  • 入口类 A 存在 O.abc 这个方法,也就是 A[O] -> O.abc;如果O是一个动态代理类,O的 invoke方法存在 .f的方法,便可以漏洞利用了
A[O] -> O.abc
O[02] invoke -> 0.2f //此时将B 去替换为 O2
最后 --->
O[B] invoke -> b.f //达到漏洞利用效果

image.png
反序列化漏洞中的应用

  • readObject->反序列化自动执行
  • 而invoke->有调用函数
  • 拼接两条链:任意->固定
  • 在CC第一条链和jdk 7u21那两条链使用了动态代理。

属于这种类型:入口类参数中包含可控类,该类又调用其他危险方法的类,readObject时调用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MIPI RFFE接口

1. 概况 MIPI RFFE是一种专门针对当前及未来无线系统在射频(RF)前端控制界面规范。随着手机射频系统日趋复杂,业界需要一个单一控制界面解决方案。MIPI联盟的RF前端控制界面(RFFE)规范通过提供一个可连接到收发器或无线电的总线界面解决了这一难题,可用于…

vue中使用图片url直接下载图片

vue中使用图片url直接下载图片 // 下载图片downloadByBlob(url, name) {let image new Image()image.setAttribute(crossOrigin, anonymous)image.src urlimage.onload () > {let canvas document.createElement(canvas)canvas.width image.widthcanvas.height image…

《自动机理论、语言和计算导论》阅读笔记:p68-p114

《自动机理论、语言和计算导论》学习第4天,p68-p114总结,总计47页。 一、技术总结 1.inverted indexes 明白单词的意思是“反转的索引”,但是不明白其在书中具体指什么,去查询资料的话需要花很不多时间,先继续往下看…

springboot婚庆系统

摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于婚庆系统当然也不能排除在外,随着网络技术的不断成熟,带动了婚庆系统,它彻底改变了过去传统的管理方式…

学生党开放式运动耳机怎么选?五款超高销量高性价比品牌推荐

开放式运动耳机成为了许多人的运动首选装备,想要在众多的开放式耳机中找到一款价格亲民,且性能在线高性价比的开放式运动耳机可并非那么简单,所以今天我就来为大家推荐五款超高销量、高性价比的运动耳机品牌。 在推荐之前,整理了…

Java复习第十二天学习笔记(JDBC),附有道云笔记链接

【有道云笔记】十二 3.28 JDBC https://note.youdao.com/s/HsgmqRMw 一、JDBC简介 面向接口编程 在JDBC里面Java这个公司只是提供了一套接口Connection、Statement、ResultSet,每个数据库厂商实现了这套接口,例如MySql公司实现了:MySql驱动…

继承练习题目

练习 练习1: 定义一个学生类Student,它继承自Person类 练习2: (1)定义一个ManKind类,包括 成员变量int sex和int salary; 方法void manOrWoman():根据sex的值显示“man”(sex1)或者“woman”(sex0)&…

异常-模块-包-Python

师从黑马程序员 异常的概念 异常演示 捕获异常的方法 try:fopen("D:/abc.txt","r",encoding"UTF-8") except:print("出现异常了,因为文件不存在,我将open的模式,改为w模式去打开")fopen("D:/a…

前端小白如何理解mvc mvp mvvm

架构、框架、设计模式是都是啥? 架构:抽象出来不同组织或者对象亦或是简单组件,根据需求和各个单元的功能,进行组合排列。 从而完成系统的运行或者是实现目标。 框架:使用什么样的规则,什么样的开发语言&…

武汉星起航:各大企业力挺亚马逊,共筑跨境电商新生态

亚马逊电商平台作为全球领先的跨境电商巨头,一直以来都备受各大企业的青睐与支持。这些企业通过与亚马逊合作,共同拓展市场、提升品牌影响力,实现了互利共赢的局面。武汉星起航将浅析各大企业对亚马逊电商平台的支持,展现其共筑强…

项目亮点—动态线程池管理工具

问题 你是否在项目中使用线程池遇到过以下问题? 1.创建线程池核心参数不好评估,随着业务流量的波动,极有可能出现生产故障。 2.不支持优雅关闭,当项目关闭时,大量正在运行的线程池任务被丢弃。 3.不支持运行时监控…

你该选择哪个职业呢?数据科学家、数据分析师和数据工程师

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

Taskflow:子流任务(Subflow Tasking)

创建Subflow DAG任务中,有一种常见的场景,一个任务可能在执行期间产生新的任务,然后紧接着执行新任务。 之前提到的静态图就没有办法实现这样一个功能了,所以Taskflow提供了另一种流的节点:Subflow,Subflo…

gpt 3d三角形 重心坐标填充 沿x轴炫赵师傅

go import pygame from pygame.locals import * import sys import math# 初始化Pygame pygame.init()# 设置窗口大小 width, height 800, 600 screen pygame.display.set_mode((width, height)) pygame.display.set_caption(3D Triangle Fill with Barycentric Coordinates)…

zabbix主动发现,注册及分布式监控

主动发现 结果 主动注册 结果 分布式监控 服务机:132 代理机:133 客户端:135 代理机 数据库赋权: 代理机配置 网页上配置代理 客户端配置 网页上配置主机 重启代理机服务 网页效果

写作类AI推荐(二)

本章要介绍的写作AI如下: 火山写作 主要功能: AI智能创作:告诉 AI 你想写什么,立即生成你理想中的文章AI智能改写:选中段落句子,可提升表达、修改语气、扩写、总结、缩写等文章内容优化:根据全文…

【LV16 day2 平台总线驱动开发---名称匹配】

一、总线、设备、驱动 硬编码式的驱动开发带来的问题: 垃圾代码太多结构不清晰一些统一设备功能难以支持开发效率低下 1.1 初期解决思路:设备和驱动分离 ​ struct device来表示一个具体设备,主要提供具体设备相关的资源(如寄…

sadtalker学习用于风格化音频驱动单图像说话人脸动画的真实 3D 运动系数的应用

论文出处 https://arxiv.org/abs/2211.12194 使用方法 1. 打开项目的colab链接 https://colab.research.google.com/github/Winfredy/SadTalker/blob/main/quick_demo.ipynb#scrollTofAjwGmKKYl_I 在examples/source_image文件夹中添加希望动起来说话的图片,这…

厦门攸信技术亮相新技术研讨会,展现物流自动化解决方案新高度!

今日,厦门攸信信息技术有限公司受邀参加了一场备受行业关注的电子制造高端盛会——一步步新技术研讨会,凭借卓越的智能制造与物流自动化技术在会议中大放异彩。作为一家引领行业发展的企业,厦门攸信技术不仅展示了其深厚的技术底蕴&#xff0…

java全排列(力扣Leetcode46)

全排列 力扣原题链接 问题描述 给定一个不含重复数字的数组 nums,返回其所有可能的全排列。你可以按任意顺序返回答案。 示例 示例 1: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2…