Java 反序列化 - commons collection 之困(一)

news/2024/5/19 3:31:11 标签: java, 反射, class
class="baidu_pl">
class="article_content clearfix">
class="markdown_views prism-atom-one-dark">

01多余的碎碎念

说到 class="tags" href="/tags/JAVA.html" title=java>java 反序列化,去搜索的话能看到网上有很多分析关于 commons collection 利用链的文章,emm 我一开始看不懂,看到很多代码的图头晕。

这篇文章的话其实是我跟着 p 神的文章一路走下来的,所以整个逻辑会按照 p 神的文章走。那对于class="tags" href="/tags/FanShe.html" title=反射>反射、动态代理也有一些自己的理解,所以就记录下来。希望也给你们多一个角度的理解。

02class="tags" href="/tags/FanShe.html" title=反射>反射

为什么要先讲class="tags" href="/tags/FanShe.html" title=反射>反射?因为你去看他的利用链的实现,会发现都会运用到class="tags" href="/tags/FanShe.html" title=反射>反射。

class="tags" href="/tags/JAVA.html" title=java>java 中有两个类用来执行命令,一个是 Runtime ,一个是 ProcessBuilder 。那这两个类都是没有实现 Serializable (序列化)接口的,也就是不能进行反序列化,我们想想,如果我们执行命令的类不能进行反序列化,也就是不能利用反序列化漏洞还原该类,那我们是不是也就不能执行命令了?这时候我们其实就可以通过class="tags" href="/tags/FanShe.html" title=反射>反射来创建该类的对象【也就是常说的运行时对象】,调用该类的方法。

所以我们首先来介绍一下class="tags" href="/tags/FanShe.html" title=反射>反射,只要我们知道需要用的类名、方法名及参数类型,我们就能通过class="tags" href="/tags/FanShe.html" title=反射>反射机制创建任意类对象、调用任意类方法。

举一较常用的例子:

package com.govuln;

import class="tags" href="/tags/JAVA.html" title=java>java.lang.reflect.InvocationTargetException;

public class test {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = Runtime.class;
clazz.getMethod(“exec”, String.class).invoke(clazz.getMethod(“getRuntime”).invoke(null), “calc.exe”);
}
}
这里其实就是通过class="tags" href="/tags/FanShe.html" title=反射>反射实现了调用计算器的效果,如果不用class="tags" href="/tags/FanShe.html" title=反射>反射,我们正常代码逻辑就是 Runtime.getRuntime().exec(“calc”); 就好了。

image.png

那么接下来为了理解上面的代码一步步看class="tags" href="/tags/FanShe.html" title=反射>反射的语法。

我们从下往上推,最开始看他方法调用的部分:

正常方法调用语法:obj.方法(args)

class="tags" href="/tags/FanShe.html" title=反射>反射方法调用语法:方法.invoke(Object obj, Object… args) ,invoke 中传入的参数为调用此方法的对象,及方法需传入的参数值。

而此时的方法也应是通过class="tags" href="/tags/FanShe.html" title=反射>反射得到的。语法:class.getMethod(String name, Class<?>… parameterTypes) ,getMethod 方法中传入的为我们需调用的方法名以及方法的参数类型。

而这里的 class 就是字节码文件对象,也是类在内存中的体现。字节码文件也就是 class="tags" href="/tags/JAVA.html" title=java>java 源文件编译后生成的 .class 文件,JVM 将 .class 文件加载到内存执行,将编译后的 .class 文件当作字节码文件对象。那么获取当前 class 的语法:

1、类.class
2、Class.forName(类的全路径)
所以我们刚才代码中获取 Runtime 的字节码文件对象其实是通过第一种方式获取到的。

讲到这里前面代码中通过class="tags" href="/tags/FanShe.html" title=反射>反射执行 Runtime 的 exec 方法应该可以理解得差不多:首先获取到 Runtime 的字节码文件,接下来获取到其方法 exec ,然后进行方法调用。那这里还有一个地方就是方法调用的时候可能不明白:invoke 传入的参数,调用此方法的对象。clazz.getMethod(“getRuntime”).invoke(null) 为什么是这样生成对象的呢?那其实class="tags" href="/tags/FanShe.html" title=反射>反射获取到目标对象有两种方式,第一种就是通过上面代码中的形式,这种是通过 Runtime 去调用静态方法 getRuntime ,从而得到一个 Runtime 对象。

image.png

这里通过这种方式是因为 Runtime 类的构造方法是私有的(意味着非 Runtime 类无法访问到生成对象时需调用的构造方法,作用域的限制)。所以他有一个统一的路径去获取到 Runtime 对象,那就是通过调用静态方法 getRuntime 。那么调用静态方法时,传入的参数调用此方法的对象可以为 null,当然传入上面代码中 clazz 对象也是可以的。

到这里上面通过class="tags" href="/tags/FanShe.html" title=反射>反射执行计算器的命令应该就都能理解了。我们还讲一下第二种方式来获取目标对象哦,那就是通过基本的构造方法来获取到目标对象,在class="tags" href="/tags/FanShe.html" title=反射>反射中,我们可以通过 clazz.getDeclaredConstructor() 方法获取到类的私有构造方法,并设置 Accessible 为 true ,即可通过获取的构造器来 newInstance 获取到目标对象,newInstance 方法中传入的参数是创建目标对象时需要的初始化对象,没有则不传。所以也就是可以这样执行命令:

Class clazz = Class.forName(“class="tags" href="/tags/JAVA.html" title=java>java.lang.Runtime”);
Constructor constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Runtime runtime = (Runtime) constructor.newInstance();
clazz.getMethod(“exec”, String.class).invoke(runtime, “calc”);
那么通过另一个类来执行命令的话,大家可以自己先写一下:

class="tags" href="/tags/FanShe.html" title=反射>反射:

Class clazz = ProcessBuilder.class;
clazz.getMethod(“start”).invoke(clazz.getConstructor(List.class).newInstance(Arrays.asList(“calc”)));
正常:

ProcessBuilder processBuilder = new ProcessBuilder(“calc”);
processBuilder.start();

03动态代理

为什么要讲动态代理?emmm 因为利用链会用到。 ezgif.gif

动态代理,其实挺像相亲的【也到了要相亲的年纪,也挺和时宜 233 】。当男孩心悦于某女孩,那么肯定都会先要经过父母这关的,当父母觉得这个男孩子 ok ,那么好,你们俩去进行下一步操作。那这里父母其实就相当于我们的动态代理类,其实也相当于一个拦截过滤器的作用,使其不直接与类对象进行交互而是通过代理对象去进行交互,想要调用该类对象的某方法时:

首先获取到通过代理类生成的代理对象:Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 返回某个对象的代理对象。
第一个参数是 ClassLoader ,指明生成代理对象使用哪个类装载器;
第二个参数是指明生成哪个对象的代理对象,通过接口指定;
第三个参数是一个实现了 InvocationHandler 接口的对象,该对象有个 invoke 方法里面实现了代理对象要去做什么事的逻辑。
接下来通过代理对象调用目标对象的方法,实际上先调用了 h 的 invoke 方法,接着再去调用具体对象的方法。
可以看一个例子理解:

public class App {
public static void main(String[] args) {
InvocationHandler handler = new ExampleInvocationHandler(new HashMap());
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);
proxyMap.put(“hello”, “world”);
String result = (String)proxyMap.get(“hello”);
System.out.println(result);
}
}
public class ExampleInvocationHandler implements InvocationHandler {

protected Map map;

public ExampleInvocationHandler(Map map){
    this.map = map;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (method.getName().compareTo("get") == 0){
        System.out.println("Hook method:" + method.getName());
        return "hacked object";
    }
    return method.invoke(this.map, args);
}

}
运行结果: image.png

04不重要的结尾

好啦,讲到这里文章已经很长了,下一篇再一起分析 commons collection 的利用链吧。点个赞,分享一下吧。

image.png


http://www.niftyadmin.cn/n/702751.html

相关文章

docker下运行漏洞环境

建立一个漏洞复现的环境&#xff0c;其实和建立一个应用的步骤是类似的。只是漏洞复现环境是存在漏洞的应用而已。 对环境的搭建比较方便的方式是通过dockerfile结合docker-compose。 Dockerfile是由一系列命令和参数构成的脚本&#xff0c;这些命令应用于拉取的基础镜像并最终…

CVE-2020-1488214883weblogic未授权命令执行漏洞复现

简介 WebLogic 是美国 Oracle 公司的主要产品之一&#xff0c;是商业市场上主要的 J2EE 应用服务器软件&#xff0c;也是世界上第一个成功商业化的 J2EE 应用服务器&#xff0c;在 Java 应用服务器中有非常广泛的部署和应用。 概述 10 月 21 日&#xff0c;Oracle 官方发布数…

Windows防火墙及Linux防火墙

防火墙概述 相关实验 <网络防火墙> 防火墙是位于两个或多个网络间&#xff0c;实施网间访问控制的一组组件的集合&#xff0c;满足以下条件&#xff1a;内部和外部之间的所有网络数据流必须经过防火墙&#xff1b;只有符合安全策略的数据流才能通过防火墙&#xff1b;…

Windows域认证机制

文章目录Windows认证机制Windows认证基础本地认证网络认证hashcat破解net-ntlm hash域认证Kerberos认证协议的基础概念Kerbreros认证流程1. 用户登录2. 请求身份认证2.1 客户端向AS(身份认证服务)发送认证请求2.2 AS确认Client端登录者用户身份3. 请求服务授权3.1 客户端向TGS发…

de1ay靶场实战

文章目录de1ay环境WEB信息收集weblogic 10.3.6WeblogicScanWeblogic-EXP反弹shellProxy代理reGeorg proxychainsmsf socks代理cs socks代理dump hashmimikatzpowershellprocdumpcs的logonpasswordsLaZagne横向移动-PTHCS-PTH横向移动-PTTms14-068de1ay 环境 所有机器密码&…

威胁狩猎:基于ELK的日志监控

威胁狩猎&#xff1a;基于ELK的日志监控 0x0 概述 ELK Stack即以前的Elastic Stack&#xff0c;Elk Stack是Elastic公司专门为集中化日志管理设计的免费开源软件组合。它允许搜索、分析和可视化来自不同来源的日志。 如在ubuntu上安装配置ELK Stack&#xff0c;需要如下先决…

内网渗透测试:利用DCOM进行横向渗透

图片 COM COM即组件对象模型(Component Object Model&#xff0c;COM) &#xff0c;是基于 Windows 平台的一套组件对象接口标准&#xff0c;由一组构造规范和组件对象库组成。COM是许多微软产品和技术&#xff0c;如Windows媒体播放器和Windows Server的基础。 一般的对象是由…

服务端模板注入漏洞SSTI

所有用户的输入都存在风险 tempalte "Bio:{{user.bio}}" render(template)数据交互Bio&#xff08;user对象的bio属性&#xff09; 当user.bio是正常输入时&#xff0c;例如&#xff1a;Bio:{{7*7}}&#xff0c;那就是正常的显示输入。 当user.bio是恶意输出时&am…