java基础漏洞学习----基础命令执行漏洞

java基础漏洞学习----基础命令执行漏洞

基础命令执行常见方法

1.ProcessBuilder

package com.example.servletdemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Command1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        String ip = request.getParameter("ip");
        if(ip!=null && !ip.isEmpty()){
            try{
                String command = "ping "+ip;
                ProcessBuilder pb = new ProcessBuilder("cmd","/c",command);
                Process p = pb.start();
                BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                StringBuilder result = new StringBuilder();
                String line;
                while((line = reader.readLine())!=null){
                    result.append(line).append("\n");
                }

                response.getWriter().print(result.toString());
            } catch (IOException e){
                e.printStackTrace();
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        } else {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        }
    }
}

web.xml中添加路由

    <servlet>
        <servlet-name>Command1</servlet-name>
        <servlet-class>com.example.servletdemo.Command1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Command1</servlet-name>
        <url-pattern>/command1</url-pattern>
    </servlet-mapping>

传参ip=127.0.0.1%26dir
但是好像命令里面不让有反斜杠

2.Runtime exec
1)Runtime exec执行字符串参数和数组参数
1.字符串参数
稍微修改一下代码

import java.lang.Runtime;

...

                String command = "ping "+ip;
                Process p = Runtime.getRuntime().exec(command);

此时再传入ip=baidu.com%26dir会报错,显然将传入的参数当一个整体让ping命令执行了

然后再改

String command = "cmd.exe /c ping "+ip;

ip=baidu.com%26dir 这样可以了

2.数组参数
再改

String[] command = {"cmd.exe","/c","ping"+ip};

ip=baidu.com%26dir 这样可以了 但是不让有空格
3.深入理解其原因
先选择exec,然后ctrl+右键进入类

发现

  public Process exec(String cmdarray[]) throws IOException {
        return exec(cmdarray, null, null);
    }

然后再跟进exec

    public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }


然后在当前类里搜索exec 发现如果传入的是字符串类型的话会经过StringTokenizer处理

    public Process exec(String command, String[] envp, File dir)
        throws IOException {
        if (command.isEmpty())
            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);
    }

根据此处的英文注释发现\t\n\r\f会对传入的字符串进行分割,分割完成后会返回一个cmdarray数组,所以传入字符串参数和传入数组参数返回结果不同

例如linux命令

String command = "/bin/sh -c \"ping -t 3 baidu.com;id\"";

会被拆分为

{"/bin/sh","-c",""ping","-t","3","baidu.com;id","""}

相当于ping 'baidu.com;id'这个域名
3.Reflect Method
用途:jsp免杀木马
通过Class.forName获得恶意类
通过runtimeClass.getMethod获得恶意类中的方法
使得恶意类和恶意方法可以通过编码进行混淆绕过静态检测

package com.example.servletdemo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Command3 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");

        String ip = request.getParameter("ip");
        if(ip!=null && !ip.isEmpty()){
            try{

                // 获取Runtime类
                Class<?> runtimeClass = Class.forName("java.lang.Runtime");
                // 获取getRuntime方法
                Method getRuntimeMethod = runtimeClass.getMethod("getRuntime");
                // 调用getRuntime方法获取Runtime对象
                Object runtimeObject = getRuntimeMethod.invoke(null);
                // 获取exec方法
                Method execMethod = runtimeClass.getMethod("exec", String.class);
                // 执行命令
                String command = "cmd.exe /c ping "+ip;
                Process p = (Process) execMethod.invoke(runtimeObject, command);

                BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
                StringBuilder result = new StringBuilder();
                String line;
                while((line = reader.readLine())!=null){
                    result.append(line).append("\n");
                }

                response.getWriter().print(result.toString());
            } catch  (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException | IOException e ){
                e.printStackTrace();
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
        } else {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        }
    }
}

ip=baidu.com%26dir

代码审计

搜索ProcessBuilder,Process,exec,Runtime,getRuntime,追踪反射类等等

posted @ 2023-10-21 11:09  BattleofZhongDinghe  阅读(82)  评论(0编辑  收藏  举报