ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

JAVA审计-命令执行

2022-03-03 01:03:28  阅读:239  来源: 互联网

标签:审计 cmd JAVA ProcessBuilder resp req len 命令 Runtime


前言

审计中最直接shell的还是rce,本篇记录下java中命令执行。

0x01 Runtime执行

public class LocalRuntime extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String cmd = req.getParameter("cmd");
        InputStream ins = Runtime.getRuntime().exec(cmd).getInputStream();
        ServletOutputStream sos = resp.getOutputStream();
        int len;
        byte[] bytes = new byte[1024];
        while ((len = ins.read(bytes))!=-1){
            sos.write(bytes, 0, len);
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

image-20220302182501427

0x02 反射Runtime执行

public class ReflactRuntime extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        String cmd = req.getParameter("cmd");
        try {
            Class cls = Class.forName("java.lang.Runtime");
            Constructor constructor = cls.getDeclaredConstructor();
            constructor.setAccessible(true);
            Object runtime = constructor.newInstance();
            Method exec = cls.getMethod("exec", String.class);
            Process process = (Process) exec.invoke(runtime, cmd);

            InputStream ins = process.getInputStream();
            int len;
            byte[] bytes = new byte[1024];
            ServletOutputStream sos = resp.getOutputStream();
            while ((len = ins.read(bytes)) != -1){
                sos.write(bytes, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

image-20220302234235108

执行过程为:

  • 反射获取Runtime的class对象

  • 获取Runtime构造方法

  • newInstance一个新Runtime的实例对象

  • 获取exec方法

  • invoke激活执行

0x03 ProcessBuilder 执行

ProcessBuilder此类用于创建操作系统进程。每个ProcessBuilder实例管理进程属性的集合。 start()方法使用这些属性创建一个新的Process实例。 start()方法可以从同一实例重复调用,以创建具有相同或相关属性的新子进程。

ProcessBuilder.start()Runtime.exec方法都可以创建一个本机进程并返回一个Process子类的Process (Runtime.exec底层调用的也是ProcessBuilder.start()),可以用来控制进程并获取有关它的信息。

public class ProccessBuilder extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        InputStream ins = new ProcessBuilder(req.getParameterValues("cmd")).start().getInputStream();
        ServletOutputStream sos = resp.getOutputStream();
        int len;
        byte[] buffer = new byte[1024];
        while ((len = ins.read(buffer)) != -1){
            sos.write(buffer,0, len);
        }

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

image-20220303002556255

ProcessBuilder.start()和Runtime.exec()的一些区别:

ProcessBuilder.start() 和 Runtime.exec()传递的参数有所不同,Runtime.exec()可接受一个单独的字符串,这个字符串是通过空格来分隔可执行命令程序和参数的;也可以接受字符串数组参数。

而ProcessBuilder的构造函数是一个字符串列表或者数组。列表中第一个参数是可执行命令程序,其他的是命令行执行是需要的参数。

0x04 反射ProcessBuilder执行

@WebServlet("/reflprocessbuild")
public class reflProcessBuild extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            String arg = req.getParameter("cmd");
            List<String> cmd = Arrays.asList(arg);
            System.out.println(cmd);

            Class cls = Class.forName("java.lang.ProcessBuilder");
            Constructor constructor = cls.getConstructor(List.class);
            constructor.setAccessible(true);
            Object pb = constructor.newInstance(cmd);
            Method start = cls.getMethod("start");
            Process process  = (Process) start.invoke(pb);
            InputStream ins = process.getInputStream();

            int len;
            byte[] buffer = new byte[1024];
            ServletOutputStream os = resp.getOutputStream();
            while ((len = ins.read(buffer)) != -1){
                os.write(buffer, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }
}

image-20220303003331124

这里需要注意有几点是不同于反射调Runtime的地方

1、首需要用List.class占位调用getConstructor(List.class)获取ProcessBuilder的有参构造。

2、传入的参数需要用Arrays.asList做一下处理,因为调的是List类型的有参构造。

总结

审计中的函数

java.lang.Runtime
java.lang.Runtime.getRuntime()
java.lang.Runtime.getRuntime().exec
getMethod().invoke()
java.lang.ProcessBuilder
java.lang.ProcessBuilder.start()
java.lang.ProcessImpl
java.lang.UNIXProcess
...

参考

https://www.cnblogs.com/CoLo/p/15240834.html

https://www.cnblogs.com/nice0e3/p/13708704.html

https://www.cnblogs.com/nice0e3/p/13494147.html

标签:审计,cmd,JAVA,ProcessBuilder,resp,req,len,命令,Runtime
来源: https://www.cnblogs.com/N0r4h/p/15957904.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有