探究使用反射进行除Runtime的命令执行方法

admin 2024年10月18日23:04:51评论7 views字数 2745阅读9分9秒阅读模式

扫码领资料

获黑客教程

免费&进群

探究使用反射进行除Runtime的命令执行方法
探究使用反射进行除Runtime的命令执行方法

概述

在RASP等安全产品防护严密的现在,普通的寻找Runtime.getRuntime().exec(cmds)的调用已经成为了一件不现实的事情。

同样的,在Java中盛行的反序列化漏洞中,如果将RCE的功能简单的通过Runtime.getRuntime().exec(cmds)这种结构来进行实现可能大概率也不能达到我们的目的,所以探索一下Runtime的底层实现,使用更加底层且复杂的调用来进行RCE功能的实现相对来说更加的可行。

这里主要是对Java中多种命令执行的方式跟踪源码进行原理分析、构造利用代码、集成自研工具。

前置

首先需要对Java中的反射机制有着基本的掌握:

通过反射的方式,我们可以获取到任何类的构造方法,类方法,成员变量,且能够获取对应类对象进行对应方法的调用等等目的:

  1. 获取Class类对象

    对于类对象的获取,主要可以通过Class.forName / loadClass的方式来获取,值得注意的是,在调用Class.forName进行类的加载的时候,将会调用static方法。

  1. Class.forName("java.lang.Runtime")

探究使用反射进行除Runtime的命令执行方法

  1. 获取对应类的构造方法

    对于获取类的构造方法,主要可以通过getConstructorgetDeclaredConstructor这两种方法来进行实现。

探究使用反射进行除Runtime的命令执行方法

探究使用反射进行除Runtime的命令执行方法

两者的区别主要是前者不能够反射获取private修饰的构造方法,而后者能够获取,

所以通常使用后者进行构造函数的获取,传入的参数就是对应构造方法的参数类:

  1. clazz.getDeclaredConstructor(type.class)

  2. clazz.getConstructor(type.class)

  1. 反射获取成员变量

和构造方法类似的,存在有getFieldgetDeclaredField两个不同的获取方法,区别和构造函数类似

  1. clazz.getField(name)

  2. clazz.getDeclaredField(name)

  1. 反射获取类方法

    同样具有getMethodgetDeclaredMethod两种。

  2. ……………

一个普通的命令执行是:

  1. Runtime.getRuntime().exec("calc");

如果使用反射机制,可以是:

  1. Class.forName("java.lang.Runtime").getMethod("exec",String.class).invoke(runtime,"calc");

或者是其他的一些使用反射机制的变形

command

跟踪Runtime

首先我们跟踪Runtime执行命令的过程

探究使用反射进行除Runtime的命令执行方法

在这里接收一个String类型的参数,调用exec的另一个重在方法对参数进行处理,将其通过分隔符,将其封装成了数组对象(这里就是一个字符串)

探究使用反射进行除Runtime的命令执行方法

之后通过参数是String[]类型的另一个重载方法,通过调用ProcessBuilder类的方法进行执行

探究使用反射进行除Runtime的命令执行方法

ProcessBuilder#start方法中,将命令传递给了ProcessImpl#start方法进行处理

探究使用反射进行除Runtime的命令执行方法

windows

在windows中主要是在ProcessImpl的构造方法中调用了create方法

探究使用反射进行除Runtime的命令执行方法

这个create方法是通过win32的方式创建了一个进程

探究使用反射进行除Runtime的命令执行方法

linux

在linux下,在ProcessImpl#start的调用中将会创建一个UNIXProcess对象并返回

探究使用反射进行除Runtime的命令执行方法

探究使用反射进行除Runtime的命令执行方法

UNIXProcess类的构造方法中,调用了forkAndExec这个native方法

探究使用反射进行除Runtime的命令执行方法

创建了一个一个进程,并返回了对应进程的pid。

构造命令执行

ProcessBuilder#start

在上面的流程分析中,知道了在Runtime.getRuntime().exec()方法调用的下一层就是使用ProcessBuilder#start方法。

如果hook掉了我们可以通过使用ProcessBuilder类来进行命令执行的构造:

  1. newProcessBuilder("calc").start();

或者使用反射的思路构造:

  1. //method_1

  2. Class pro =Class.forName("java.lang.ProcessBuilder");

  3. ((ProcessBuilder) pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).start();

  4. //method_2

  5. Class pro =Class.forName("java.lang.ProcessBuilder");

  6. pro.getMethod("start").invoke(pro.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));

  7. //method_3

  8. Class pro =Class.forName("java.lang.ProcessBuilder");

  9. ((ProcessBuilder) pro.getConstructor(String[].class).newInstance(newString[][]{{"calc.exe"}})).start();

  10. //method_4

  11. Class pro =Class.forName("java.lang.ProcessBuilder");

  12. pro.getMethod("start").invoke(pro.getConstructor(String[].class).newInstance(newString[][]{{"calc.exe"}}));

ProcessImpl

从上面的分析可以知道,在windows环境下的JDK:

ProcessImpl类的构造方法将会调用create方法执行native方法进行命令执行

探究使用反射进行除Runtime的命令执行方法

所以我们只需要反射获取ProcessImpl类的构造方法并实例化就会执行我们的恶意逻辑。

UNIXProcess

上面是针对windows的方式,针对linux,在前面的分析中知道主要是在其start方法中调用了UNIXProcess类的构造方法

探究使用反射进行除Runtime的命令执行方法

执行forkAndExec这个native方法进行命令执行

other

甚至于,我们知道最后主要是在create方法(windows)、forkAndExec方法(linux)中执行命令,我们同样可以通过反射这两个方法进行命令执行

原文地址:https://xz.aliyun.com/t/1244

声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。

原文始发于微信公众号(白帽子左一):探究使用反射进行除Runtime的命令执行方法

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月18日23:04:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   探究使用反射进行除Runtime的命令执行方法https://cn-sec.com/archives/1880654.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息