the_open_door
café
ESEN
← Volver al índice

Null Byte Injection (%00) in LFI

El null byte %00 es una técnica clásica para sortear un filtro de extensión en inclusiones de ficheros (LFI) sobre PHP anterior a 5.3.4. El patrón vulnerable es un código que toma un parámetro del usuario y le añade un sufijo fijo antes de incluirlo:

require_once($_GET['classes_dir'] . '/class.cs_phpmailer.php');

Como la ruta siempre termina en .php (o .html, etc.), no podemos incluir directamente /etc/passwd: el código buscaría /etc/passwd/class.cs_phpmailer.php. Aquí entra el %00: en aquellas versiones de PHP, las rutas se pasan a funciones de C que interpretan el byte nulo como fin de cadena. Al enviar %00, todo lo que el código añade después se descarta, y el servidor incluye exactamente el fichero pedido:

curl "http://<ip>/.../?classes_dir=../../../../../../etc/passwd%00" --path-as-is

Dos detalles del payload: los ../ repetidos suben hasta la raíz (sobran algunos a propósito: pasarse es inofensivo, quedarse corto no llega), y --path-as-is evita que curl normalice el ../.

Combinado con php://filter. Si el objetivo es leer código fuente PHP (que de otro modo se ejecutaría en vez de mostrarse), se envuelve el recurso en el wrapper php://filter con convert.base64-encode antes del %00:

curl "http://<ip>/.../?classes_dir=php://filter/convert.base64-encode/resource=../../config.php%00" --path-as-is | base64 -d

Por qué pasa. Una capa (PHP) construye una ruta con entrada del usuario sin canonicalizarla, y otra capa (las funciones de C subyacentes) trata \0 como terminador. El mismo truco aparece en path traversal antiguos como CVE-2010-2861.

Cómo detectarlo. La firma en el log de acceso es un %00 (byte nulo codificado) en un parámetro de inclusión, a menudo junto a secuencias ../ y al wrapper php://filter; ninguna petición legítima lleva un null byte, así que un WAF que lo detecte lo bloquea de inmediato. Un PHP < 5.3.4 en el banner es la exposición previa, y la lectura por el proceso web de un fichero fuera del árbol esperado (/etc/passwd, config.php) tras esa petición confirma el traversal.

Defensa. Actualizar PHP (en 5.3.4+ el %00 en rutas dejó de truncar), y sobre todo validar y canonicalizar cualquier ruta construida con entrada del usuario en vez de concatenar sufijos.

Máquinas donde se aplica

  • PayDayProving Grounds Practice