Inyección De Comandos En Java

Estado
Review

Introducción
Las vulnerabilidades de este tipo permiten a un atacante inyectar arbitrariamente comandos del sistema en una aplicación. Estos comandos se ejecutan al mismo nivel de privilegios que la aplicación Java y proveen al atacante una funcionalidad similar a la de una Shell de Sistema Operativo. En Java, Runtime.exec es comúnmente usado para invocar a un nuevo proceso, pero esto no invoca una nueva Shell de comandos, lo que significa que usualmente encadenando o entubando múltiples comandos juntos no funciona. La inyección de comandos sin embargo es posible si el proceso engendrado con Runtime.exec es una Shell como command.com, cmd.exe o /bin/sh..

Ejemplo 1
El código detallado a continuación permite a un usuario el control de los argumentos del comando de Windows find. Mientras el usuario no posea control absoluto sobre los argumentos, no es posible inyectar comandos adicionales. Por ejemplo, ingresando “test & del file” no causará que el comando del se ejecute. Dado que Runtime.exec tokeniza la cadena de comando y luego invoca el comando find usando los parámetros “test”, “&”, “del” y “file”.

import java.io.*;

public class Example1 { public static void main(String[] args) throws IOException { if(args.length != 1) { System.out.println("No arguments"); System.exit(1); }		Runtime runtime = Runtime.getRuntime; Process proc = runtime.exec("find" + " " + args[0]); InputStream is = proc.getInputStream; InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine) != null) { System.out.println(line); }	} }

Ejemplo 2
El código a continuación invoca una shell del sistema para ejecutar un commando no ejecutable usando lo ingresado por el usuario como parámetros. Comandos de Windows no ejecutables tales como dir y copy son parte del intérprete de comandos y por ende no pueden ser directamente invoados por Runtime.exec. En este caso, la inyección de comandos es posible y un atacante puede encadenar múltiples comandos juntos. Por ejemplo ingresando, “.& echo hello” causará que el comando dir liste los contenidos del directorio actual y el comando echo imprima un mensaje de saludo.

import java.io.*;

public class Example2 { public static void main(String[] args) throws IOException { if(args.length != 1) { System.out.println("No arguments"); System.exit(1); }		Runtime runtime = Runtime.getRuntime; String[] cmd = new String[3]; cmd[0] = "cmd.exe" ; cmd[1] = "/C"; cmd[2] = "dir " + args[0]; Process proc = runtime.exec(cmd); InputStream is = proc.getInputStream; InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line; while ((line = br.readLine) != null) { System.out.println(line); }	} }

Mejores Prácticas
Los desarrolladores deben evitar invocar la shell usando Runtime.exec para llamar a comandos del sistema operativo y en su defecto deben usar la API de Java. Por ejemplo, en vez de llamar lsor dir desde la sell se debe usar la clase Java File para la función de listado. Si es necesario que el usuario deba ingresar datos y pasarlos hacía Runtime.exec, y luego usar expresiones regulares para validar el ingreso.