Basic Bypasses
Last updated
Last updated
En la sección anterior, vimos varios tipos de ataques que podemos usar para diferentes tipos de vulnerabilidades de LFI. En muchos casos, podríamos encontrarnos con una aplicación web que aplica diversas protecciones contra la inclusión de archivos, por lo que nuestras cargas útiles de LFI habituales no funcionarían. Aun así, a menos que la aplicación web esté debidamente protegida contra la entrada maliciosa de usuarios de LFI, podríamos eludir las protecciones existentes y lograr la inclusión de archivos.
Uno de los filtros más básicos contra LFI es el filtro de búsqueda y reemplazo, que simplemente elimina subcadenas de ( ../
) para evitar recorrer rutas. Por ejemplo:
El código anterior pretende evitar el cruce de rutas y, por lo tanto, inutilizar LFI. Si probamos las cargas útiles de LFI que probamos en la sección anterior, obtenemos lo siguiente:
Vemos que ../
se eliminaron todas las subcadenas, lo que resultó en una ruta final de ./languages/etc/passwd
. Sin embargo, este filtro es muy inseguro, ya que no es recursively removing
la ../
subcadena, ya que se ejecuta una sola vez en la cadena de entrada y no aplica el filtro a la cadena de salida. Por ejemplo, si usamos ....//
como carga útil, el filtro se eliminaría ../
y la cadena de salida sería ../
, lo que significa que aún podríamos recorrer la ruta. Intentemos aplicar esta lógica a la función include /etc/passwd
de nuevo:
Como podemos ver, la inclusión se realizó correctamente esta vez y podemos leer /etc/passwd
correctamente. La ....//
subcadena no es la única derivación que podemos usar, ya que podemos usar ..././
`or` ....\/
y otras cargas útiles LFI recursivas. Además, en algunos casos, escapar la barra diagonal también puede funcionar para evitar filtros de recorrido de ruta (p. ej., `` ....\/
), o añadir barras diagonales adicionales (p. ej., ` ....////
`) .
Algunos filtros web pueden impedir los filtros de entrada que incluyen ciertos caracteres relacionados con LFI, como un punto .
o una barra diagonal /
para recorrer rutas. Sin embargo, algunos de estos filtros pueden omitirse mediante la codificación URL de nuestra entrada, de modo que ya no incluya estos caracteres incorrectos, pero se decodifique de nuevo como nuestra cadena de recorrido de ruta una vez que alcance la función vulnerable. Los filtros principales de PHP en las versiones 5.3.4 y anteriores eran específicamente vulnerables a esta omisión, pero incluso en versiones más recientes podemos encontrar filtros personalizados que pueden omitirse mediante la codificación URL.
Si la aplicación web de destino no permitía .
el uso /
de ``` en nuestra entrada``, podemos codificar la URL ../
en ` %2e%2e%2f
``, lo que podría eludir el filtro. Para ello, podemos usar cualquier codificador de URL en línea o la herramienta Burp Suite Decoder, como se indica a continuación:
Intentemos usar esta carga útil LFI codificada contra nuestra aplicación web vulnerable anterior que filtra ../
cadenas:
Como podemos ver, también logramos eludir el filtro y usar el recorrido de ruta para leer /etc/passwd
. Además, podemos usar Burp Decoder para codificar la cadena codificada de nuevo y obtener una double encoded
cadena, lo que también permite eludir otros tipos de filtros.
Algunas aplicaciones web también pueden usar expresiones regulares para garantizar que el archivo incluido se encuentre en una ruta específica. Por ejemplo, la aplicación web que analizamos podría aceptar únicamente rutas que se encuentren en el ./languages
directorio, como se indica a continuación:
Para encontrar la ruta aprobada, podemos examinar las solicitudes enviadas por los formularios existentes y ver qué ruta utilizan para la funcionalidad web normal. Además, podemos realizar pruebas de fuzzing en directorios web con la misma ruta y probar diferentes hasta encontrar una coincidencia. Para evitar esto, podemos usar el recorrido de ruta e iniciar nuestra carga útil con la ruta aprobada, y luego usar ../
para volver al directorio raíz y leer el archivo especificado, como se muestra a continuación:
Algunas aplicaciones web pueden aplicar este filtro junto con uno de los filtros anteriores, por lo que podemos combinar ambas técnicas iniciando nuestra carga útil con la ruta aprobada y luego codificar en URL nuestra carga útil o usar una carga útil recursiva.
Como se explicó en la sección anterior, algunas aplicaciones web añaden una extensión a nuestra cadena de entrada (p. ej., .php
) para garantizar que el archivo que incluimos tenga la extensión esperada. Con las versiones modernas de PHP, es posible que no podamos evitar esto y nos veamos limitados a leer únicamente archivos con esa extensión, lo cual puede seguir siendo útil, como veremos en la siguiente sección (p. ej., para leer código fuente).
Hay un par de técnicas más que podríamos usar, pero son obsolete with modern versions of PHP and only work with PHP versions before 5.3/5.4
... Sin embargo, puede ser útil mencionarlas, ya que algunas aplicaciones web podrían seguir ejecutándose en servidores antiguos, y estas técnicas podrían ser las únicas alternativas posibles.
En versiones anteriores de PHP, las cadenas definidas tenían una longitud máxima de 4096 caracteres, probablemente debido a la limitación de los sistemas de 32 bits. Si se pasaba una cadena más larga, simplemente sería truncated
, y cualquier carácter después de la longitud máxima se ignoraría. Además, PHP solía eliminar las barras diagonales finales y los puntos simples en los nombres de ruta, por lo que si invocábamos ( /etc/passwd/.
), /.
también se truncaría, y PHP invocaría ( /etc/passwd
). PHP, y los sistemas Linux en general, también ignoran las barras diagonales múltiples en la ruta (por ejemplo, ////etc/passwd
es igual a /etc/passwd
). De forma similar, un acceso directo al directorio actual ( .
) en medio de la ruta también se ignoraría (por ejemplo, /etc/./passwd
).
Si combinamos estas dos limitaciones de PHP, podemos crear cadenas muy largas que evalúan una ruta correcta. Al alcanzar el límite de 4096 caracteres, la extensión añadida ( .php
) se trunca y obtenemos una ruta sin extensión añadida. Finalmente, es importante tener en cuenta que también necesitamos [nombre del archivo] start the path with a non-existing directory
para que esta técnica funcione.
Un ejemplo de dicha carga útil sería el siguiente:
Por supuesto, no tenemos que escribir manualmente ./
2048 veces (un total de 4096 caracteres), pero podemos automatizar la creación de esta cadena con el siguiente comando:
También podemos aumentar el número de ../
, ya que añadir más nos llevaría al directorio raíz, como se explicó en la sección anterior. Sin embargo, si usamos este método, debemos calcular la longitud completa de la cadena para asegurarnos de que solo .php
se trunque y no el archivo solicitado al final de la cadena ( /etc/passwd
). Por eso sería más fácil usar el primer método.
Las versiones de PHP anteriores a la 5.5 eran vulnerables a null byte injection
, lo que significa que añadir un byte nulo ( %00
) al final de la cadena la terminaba y no consideraba nada posterior. Esto se debe a la forma en que las cadenas se almacenan en la memoria de bajo nivel, donde deben usar un byte nulo para indicar el final, como ocurre en los lenguajes Ensamblador, C o C++.
Para explotar esta vulnerabilidad, podemos terminar nuestra carga útil con un byte nulo (por ejemplo, /etc/passwd%00
), de modo que la ruta final pasada a include()
sea ( /etc/passwd%00.php
). De esta forma, aunque .php
se añada a nuestra cadena, cualquier valor después del byte nulo se truncaría, por lo que la ruta utilizada sería /etc/passwd
, lo que nos permitiría omitir la extensión añadida.
Puede consultar el módulo para obtener más información sobre cómo eludir varios personajes incluidos en la lista negra, ya que las mismas técnicas también se pueden utilizar con LFI.