命令注入
命令执行漏洞是有些代码中需要调用到系统命令,当系统命令代码未对用户可控参数做过滤,则当用户能控制相和谐函数的参数的时候就可以把恶意命令把拼接正常命令中造成命令执行攻击。在Java中,命令执行漏洞主要包含两个主要方法,ProcessBuilder.start()、Runtime.getRuntime.exe()。
ProcessBuilder命令执行漏洞
ProcessBuilder 是 Java 中的一个类,用于创建和管理操作系统进程。它允许你在 Java 应用程序中执行系统命令。然而,如果使用不当,ProcessBuilder 可能导致命令注入漏洞。这种漏洞使得攻击者能够通过不受信任的输入执行任意命令,进而控制目标系统。
其中每个ProcessBuilder管理一个进程属性,start()方法会创建一个新的Process实例。ProcessBuilder使用方法
但是,当在输入框进行命令拼接的时候,会发现报错。这是因为在执行系统命令的时候,实际并没有获取Windows或Linux的shell,因此如果想要拼接,需要先调用一个shell。如下
总结:
命令执行漏洞是有些代码中需要调用到系统命令,当系统命令代码未对用户可控参数做过滤,则当用户能控制相和谐函数的参数的时候就可以把恶意命令把拼接正常命令中造成命令执行攻击。在Java中,命令执行漏洞主要包含两个主要方法,ProcessBuilder.start()、Runtime.getRuntime.exe()。
ProcessBuilder命令执行漏洞
ProcessBuilder 是 Java 中的一个类,用于创建和管理操作系统进程。它允许你在 Java 应用程序中执行系统命令。然而,如果使用不当,ProcessBuilder 可能导致命令注入漏洞。这种漏洞使得攻击者能够通过不受信任的输入执行任意命令,进而控制目标系统。
其中每个ProcessBuilder管理一个进程属性,start()方法会创建一个新的Process实例。
public static void main(String[] args) throws IOException {// ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "calc");ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir && calc");Process p = pb.start();// 输出结果// 命令正常执行的输出InputStream inputStream = p.getInputStream();// 命令执行失败的输出InputStream errorStream = p.getErrorStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"GBK"));String line = null;// 如果命令正确,输出结果if (inputStream != null){while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}}// 如果命令失败,输出结果if (errorStream != null){BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream,"GBK"));while ((line = errorReader.readLine()) != null) {System.out.println(line);}}bufferedReader.close();inputStream.close();p.destroy();System.out.println("执行完毕");}
ProcessBuilder命令注入案例
@GetMapping("/ping")public Map ping(String ip) throws Exception {// ProcessBuilder pb = new ProcessBuilder("ping" ,ip);ProcessBuilder pb = new ProcessBuilder("cmd","/c","ping" ,ip);Process p = pb.start();InputStream inputStream = p.getInputStream();// 命令执行失败的输出InputStream errorStream = p.getErrorStream();// 封装返回结果HashMap hashMap = new HashMap();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"GBK"));String line = null;StringBuilder result = new StringBuilder();// 如果命令正确,输出结果if (inputStream != null){while ((line = bufferedReader.readLine()) != null) {System.out.println(line);result.append(line + "<hr/>");}}// 如果命令失败,输出结果if (errorStream != null){BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream,"GBK"));while ((line = errorReader.readLine()) != null) {System.out.println(line);result.append(line + "<hr/>");}}bufferedReader.close();inputStream.close();// p.destroy();System.out.println("执行完毕");hashMap.put("data",result);return hashMap;}
现在由于IP没有做任何过滤,因此可以进行命令拼接,但是进行命令拼接还要分为不同的操作系统。
| 操作系统 | 符号 | 示例 | 说明 ||----------|-------|--------------------|----------------------------------------------------|| Windows | `&` | `cmd1 & cmd2` | 先执行`cmd1`,再执行`cmd2`。|| Windows | `&&` | `cmd1 && cmd2` | 先执行`cmd1`,如果成功则执行`cmd2`。|| Windows | `||` | `cmd1 || cmd2` | 先执行`cmd1`,如果失败则执行`cmd2`。|| Windows | `|` | `cmd1 | cmd2` | 将`cmd1`的输出作为`cmd2`的输入。|| Linux | `;` | `cmd1; cmd2` | 先执行`cmd1`,再执行`cmd2`。|| Linux | `&&` | `cmd1 && cmd2` | 先执行`cmd1`,如果成功则执行`cmd2`。|| Linux | `||` | `cmd1 || cmd2` | 先执行`cmd1`,如果失败则执行`cmd2`。|| Linux | `|` | `cmd1 | cmd2` | 将`cmd1`的输出作为`cmd2`的输入。|| Linux | `&` | `cmd1 & cmd2` | 将`cmd1`放入后台执行,然后立即执行`cmd2`。|
Runtime Exec命令执行漏洞
//执行指定的字符串命令。exec(String command)//执行由字符串数组指定的命令和参数。exec(String[] cmdArray)//执行指定的字符串命令,并在指定的环境变量下。exec(String command, String[] envp)//执行由字符串数组指定的命令和参数,并在指定的环境变量下。exec(String[] cmdArray, String[] envp)//在指定的工作目录下执行指定的字符串命令,并在指定的环境变量下。exec(String command, String[] envp, File dir)//在指定的工作目录下执行由字符串数组指定的命令和参数,并在指定的环境变量下。exec(String[] cmdArray, String[] envp, File dir)
ScriptEngineManager
在Java中,ScriptEngine 是用于执行脚本代码的 API。它是 Java Scripting API 的一部分,通常用于在 Java 应用程序中嵌入脚本语言代码。
// ====== 获取执行引擎// 创建一个 ScriptEngineManager 实例ScriptEngineManager manager = new ScriptEngineManager();// 通过 ScriptEngineManager 获取一个 JavaScript 引擎实例ScriptEngine engine = manager.getEngineByName("JavaScript");// 检查是否成功获取引擎if (engine != null) {System.out.println("JavaScript 引擎已成功加载。");} else {System.out.println("未能加载 JavaScript 引擎。");}// ==================== 执行JS代码===========ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("JavaScript");try {// 执行简单的 JavaScript 表达式engine.eval("print('Hello, World!');");// 执行带有变量的 JavaScript 代码engine.eval("var x = 10; var y = 20; var sum = x + y; print('Sum: ' + sum);");// 从 Java 调用 JavaScript 函数String script = "function greet(name) { return 'Hello, ' + name; }";engine.eval(script);Object result = engine.eval("greet('Alice');");System.out.println(result); // 输出:Hello, Alice} catch (ScriptException e) {e.printStackTrace();}}// ========================= 传递 Java 对象到 JavaScript ==================ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("JavaScript");try {// 创建一个 Java 对象Person person = new Person("John", 30);// 将 Java 对象绑定到脚本引擎的上下文中engine.put("person", person);// 在 JavaScript 中访问和修改 Java 对象的属性engine.eval("print('Name: ' + person.getName());");engine.eval("person.setName('Jane');");engine.eval("print('New Name: ' + person.getName());");} catch (ScriptException e) {e.printStackTrace();}}// ================= 执行外部的 JavaScript 文件============ScriptEngineManager manager = new ScriptEngineManager();ScriptEngine engine = manager.getEngineByName("JavaScript");try (FileReader reader = new FileReader("path/to/your/script.js")) {// 执行外部 JavaScript 文件engine.eval(reader);} catch (ScriptException | IOException e) {e.printStackTrace();}
因为scriptEngine的相关特性,可以执行java代码,例如下面代码会执行弹窗。
try {String test = "var a = mainOutput(); function mainOutput() { var x=java.lang.Runtime.getRuntime().exec("calc"); };";engine.eval(test);}catch (Exception e){}
除了以上三种,还有很多可以执行系统命令的方式,主要分的话就是两大类,一类是原生的就是Runtime和ProcessBuilder,另一类是组件,包括不限于:Groovy代码注入、scriptengine任意命令执行、JMX等等
参考链接:
Groovy代码注入
https://xz.aliyun.com/t/8231?time__1311=n4%2BxnD0Dc7eYuxmqGNnmDUx%2FRKDtKD9ACoD
scriptengine任意命令执行
https://github.com/yzddmr6/Java-Js-Engine-Payloads?tab=readme-ov-file#js%E5%8A%A0%E8%BD%BD%E4%BB%BB%E6%84%8F%E5%AD%97%E8%8A%82%E7%A0%81
原文始发于微信公众号(安全随心录):第四课-系统学习代码审计:命令执行漏洞讲解
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-



评论