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

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

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

官方文档说明:

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

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

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

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

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

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();

跟踪start方法

可以看到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);
} }
}

使用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一层层去分析也会发现一些有意思的东西。

Java审计之命令执行篇的更多相关文章

  1. Java审计之SQL注入篇

    Java审计之SQL注入篇 0x00 前言 本篇文章作为Java Web 审计的一个入门文,也是我的第一篇审计文,后面打算更新一个小系列,来记录一下我的审计学习的成长. 0x01 JDBC 注入分析 ...

  2. Java调用Linux命令执行

    调用方式 Java调用linux命令执行的方式有两种,一种是直接调用linux命令,一种是将linux命令写到.sh脚本中,然后调用脚本执行. 详细说明 直接调用:使用java中lang包下面的Run ...

  3. Java 实现 bash命令

    Java 实现 bash命令 1.BASH 命令简介 Bash,Unix shell的一种,在1987年由布莱恩·福克斯为了GNU计划而编写.1989年发布第一个正式版本,原先是计划用在GNU操作系统 ...

  4. "Java 反序列化"过程远程命令执行漏洞

    一.漏洞描述   国外 FoxGlove 安全研究团队于2015年11月06日在其博客上公开了一篇关于常见 Java 应用如何利用反序列化操作进行远程命令执行的文章.原博文所提到的 Java 应用都使 ...

  5. Redis的常用命令与Java整合及高级应用篇

    一,redis是什么? ​ 首先数据库分为关系型数据库和非关系型数据库,关系型数据库是采用关系模型来组织数据的数据库,简单来说就是二维表格模型,同时保证事务的一致性. ​ 相反非关系型数据库采用key ...

  6. Java审计之XSS篇

    Java审计之XSS篇 0x00 前言 继续 学习一波Java审计的XSS漏洞的产生过程和代码. 0x01 Java 中XSS漏洞代码分析 xss原理 xss产生过程: 后台未对用户输入进行检查或过滤 ...

  7. Java 审计之XXE篇

    Java 审计之XXE篇 0x00 前言 在以前XXE漏洞了解得并不多,只是有一个初步的认识和靶机里面遇到过.下面来 深入了解一下该漏洞的产生和利用. 0x01 XXE漏洞 当程序在解析XML输入时, ...

  8. 用命令行编译java并生成可执行的jar包

    用命令行编译java并生成可执行的jar包 1.编写源代码. 编写源文件:CardLayoutDemo.java并保存,例如:I:\myApp\CardLayoutDemo.java.程序结构如下: ...

  9. Java中使用Oracle的客户端 load data和sqlldr命令执行数据导入到数据库中

    Windows环境下测试代码: import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundExcep ...

随机推荐

  1. java实现高斯平滑

    高斯模糊也叫作高斯平滑,这里主要用来实现图像降噪.官方有入门教程:http://opencv-java-tutorials.readthedocs.io/en/latest/ 实现代码如下: pack ...

  2. ubuntu apt-mirror 同步源到本地

    1.下载 apt-mirror apt-get install apt-mirror 2.修改配置 root@wangjq:/wangjq# cat /etc/apt/mirror.list##### ...

  3. powerdesigner16.5 生成sql语句

    1.首先安装好designer. 2.打开之后新建一个project. 3.创建之后可能会生成这样的页面. 4.点击这个图标就能调出那个视图框. 5.在project处单机右键,New一个Concep ...

  4. akka-grpc - 基于akka-http和akka-streams的scala gRPC开发工具

    关于grpc,在前面的scalaPB讨论里已经做了详细的介绍:google gRPC是一种全新的RPC框架,在开源前一直是google内部使用的集成工具.gRPC支持通过http/2实现protobu ...

  5. SQL语句中IF的简单使用 - 关联leetcode 627.交换工资

    MySQL的IF既可以作为表达式用,也可在存储过程中作为流程控制语句使用,如下是做为表达式使用: IF表达式 IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 & ...

  6. 认识JavaScript中Let和Var的区别

    本文转载自:https://www.cnblogs.com/songzxblog/p/11137117.html

  7. android 数据绑定(4)实用特性及疑惑:使用控件、格式化@string/xxx、对象传递、双向数据绑定

    1.在布局内使用其它控件 1.1 效果 箭头所指3个控件的内容随输入框内容而变化. 1.2 示例代码 <?xml version="1.0" encoding="u ...

  8. HDU-4417-Super Mario(线段树+离线处理)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  9. vant ui TabBar封装

    TabBar.vue基本上是放在App.vue里面,都存在 <template> <div id="app"> <home-tab-bar :tar- ...

  10. find 用正则表达式查找符合yyyy-mm-dd-bddd模式的目录

    yyyy-dd-mm-bddd模式解释: yyyy:年份,如2020 mm:月份,如03 dd:日期,如22 -b:意为备份,-b为固定字符串 ddd:三位序列号,从001~999 符合此格式的目录名 ...