Java审计之命令执行篇

Java审计之命令执行篇0x00前言在Java中能执行命令的类其实并不多,不像php那样各种的命令执行函数。在Java中目前所知的能执行命令的类也就两种,分别是Runtime和ProcessB

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

Java审计之命令执行篇

0x00 前言

在Java中能执行命令的类其实并不多,不像php那样各种的命令执行函数。在Java中目前所知的能执行命令的类也就两种,分别是Runtime和 ProcessBuilder类。

0x01 Runtime 执行命令分析

关于Runtime具体的使用可以看这篇文章,反射去调用Runtime。

Java学习之反射篇

@WebServlet("/execServlet")
public class execServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String exec = request.getParameter("exec");
        Process res = Runtime.getRuntime().exec(exec);

        InputStream inputStream = res.getInputStream();
        ServletOutputStream outputStream = response.getOutputStream();

        int len;
        byte[] bytes = new byte[1024];
        while ((len = inputStream.read(bytes))!=-1){
            outputStream.write(bytes,0,len);


        }

这里来运行一下,传入一个命令看看能不能正常运行。

http://localhost:8080/untitled9_war_exploded/execServlet?exec=ipconfig

Java审计之命令执行篇

Java审计之命令执行篇

我们来看看他具体的实现,首先跟踪一下getRuntime()方法。

Java审计之命令执行篇

看到调用方法就不做任何的处理就直接返回了currentRuntime对象,上面可以看到currentRuntime是Runtime的实例对象。也就是说每次调用getRuntime()方法都会new一个Runtime的对象。

官方文档说明:

每个Java应用程序都有一个Runtime类的Runtime ,允许应用程序与运行应用程序的环境进行接口。 当前运行时可以从getRuntime方法获得。 
应用程序无法创建自己的此类的实例。

再来跟踪一下exec方法,看看exec方法的具体实现

Java审计之命令执行篇

exec中有多个重载方法,在跟踪返回值的exec

Java审计之命令执行篇

还是他的重载方法,再跟踪

Java审计之命令执行篇

这里会发现不一样了,返回了

return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();

在跟踪的时候会发现,我们传入的ipconfig会在cmdarray变量里面进行传入,其他值都是null。也就是说该类的底层其实还是ProcessBuilder这个类来进行实现的。

前面的Process res = Runtime.getRuntime().exec(exec);返回类型为 Process,是通过new ProcessBuilder并传入命令,再去调用start方法返回得来的。

但我们后面的res.getInputStream();,getInputStream();是怎么来的呢?Process 是一个抽象类,包含了6个抽象方法。

abstract public OutputStream getOutputStream();


abstract public InputStream getInputStream();


abstract public InputStream getErrorStream();


abstract public int waitFor() throws InterruptedException;


abstract public int exitValue();


abstract public void destroy();

跟踪一下,这几个方法,调用的方法,除了start方法外,其他的几个方法都是进行设置值。这里就不一一演示了。

return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();

Java审计之命令执行篇

跟踪start方法

Java审计之命令执行篇

可以看到start方法里面,调用了process的实现类。

0x02 ProcessBuilder中命令执行

package com.test;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

@WebServlet("/exec2Servlet")
public class exec2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String exec = request.getParameter("exec");
        ServletOutputStream outputStream = response.getOutputStream();
        ProcessBuilder processBuilder = new ProcessBuilder(exec);

        Process res = processBuilder.start();
        InputStream inputStream = res.getInputStream();
        int len ;
        byte[] bytes =new byte[1024];
        while ((len = inputStream.read(bytes))!=-1){
            outputStream.write(bytes,0,len);
        }

    }
}

Java审计之命令执行篇

使用ProcessBuilder的方式也是可以执行命令的。

0x03 内容补充

后面专门开一个标题,做一个前面知识的补充。

Process类

Process类方法:

destroy()

杀掉子进程。

exitValue()

返回子进程的出口值。

InputStream getErrorStream()

获得子进程的错误流。

InputStream getInputStream()

获得子进程的输入流。

OutputStream getOutputStream()

获得子进程的输出流。

waitFor()

导致当前线程等待,如果必要,一直要等到由该 Process 对象表示的进程已经终止。

前面会发现的一个问题在这里做一个解疑,process既然是抽象类,不能new对象,获取到他的实例类的呢?

前面我们调试代码的时候,发现了可以使用ProcessBuilder的Start方法进行返回,第二种方法就是Runtime的exec方法,但Runtime的exec方法底层依然是ProcessBuilder的Start方法进行实现的。

这里还有必要说的一个问题,ProcessBuilder与Runtime.exec()的区别是什么?

在网上查阅了一些思路得出了以下的结论。

ProcessBuilder.start() 和 Runtime.exec() 方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来控制进程状态并获得相关信息。

ProcessBuilder.start() 和 Runtime.exec()传递的参数有所不同,Runtime.exec()可接受一个单独的字符串,这个字符串是通过空格来分隔可执行命令程序和参数的;也可以接受字符串数组参数。而ProcessBuilder的构造函数是一个字符串列表或者数组。列表中第一个参数是可执行命令程序,其他的是命令行执行是需要的参数。

参考文章

https://honeypps.com/java/process-builder-quick-start/

0x04 结尾

在遇到一些问题的时候,多打debug也是个不错的选择,多打debug能比较清晰的分析到问题所在。例如调试代码的时候,可以打个debug一层层去分析也会发现一些有意思的东西。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119917.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ideal zip包激活失效破解方法

    ideal zip包激活失效破解方法,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月15日
    42
  • webstorm 2022.01.13 激活码【2021最新】

    (webstorm 2022.01.13 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/ide…

    2022年3月31日
    122
  • 牛逼plus的springboot+maven车牌识别开源系统

    牛逼plus的springboot+maven车牌识别开源系统

    2020年11月13日
    203
  • java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一「建议收藏」

    java 泛型详解-绝对是对泛型方法讲解最详细的,没有之一「建议收藏」对java的泛型特性的了解仅限于表面的浅浅一层,直到在学习设计模式时发现有不了解的用法,才想起详细的记录一下。本文参考java泛型详解、Java中的泛型方法、 java泛型详解1.概述泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。什么是泛型?为什么要使用泛型?泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传

    2022年7月8日
    18
  • SSM-Spring(1)「建议收藏」

    SSM-Spring(1)「建议收藏」SpringSpring是一个开源的免费的框架Spring是一个轻量级的,非入侵式的框架控制反转(IOC),面向切面编程(AOP)支持事务的处理,对框架整合的支持IOC理论UserDaoUserDaoImpUserSeviceUserServiceImp在之前,用户的需求可能会影响原来的代码。使用一个set。public void setUserDao(UserDao userDao){ this.userDao = userDao;}之前是主动创建对象,控制

    2022年8月9日
    5
  • 通配符掩码的计算

    通配符掩码的计算关于通配符掩码的计算我不太清楚通配符掩码具体是怎么定义的,但是在大多数初学者的印象中通配符掩码就是子网掩码取反,在网上搜索了一下也没有什么具体解释,下面是摘自百度百科的解释:路由器使用的通配符掩码(或反掩码)与源或目标地址一起来分辨匹配的地址范围,它跟子网掩码刚好相反。它不像子网掩码告诉路由器IP地址的哪一位属于网络号一样,通配…

    2022年7月24日
    27

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号