Knife
Linux Easy que explota la puerta trasera de PHP 8.1.0-dev: una cabecera User-Agentt da ejecución remota de código sin autenticar y shell como james; luego un sudo NOPASSWD sobre el binario knife, que corre Ruby, regala root.
Knife
| Máquina | SO | Dificultad | IP |
|---|---|---|---|
| Knife | Linux | Easy | 10.129.89.106 |
A tener en cuenta...
Resumen
Knife es de las que se resuelven en dos movimientos, pero cada uno tiene su gracia. El acceso no viene de una mala configuración ni de un fallo del código de la web: viene de que el servidor corre una versión de PHP que llevaba una puerta trasera metida a propósito. No un bug, una puerta trasera de verdad, fruto de uno de los incidentes de cadena de suministro más sonados que se recuerdan.
Esa puerta se abre mandando una cabecera concreta en la petición, y con ella se ejecuta código en el servidor sin credenciales de ningún tipo. De ahí a una shell como james hay un paso.
La escalada es un clásico de sudo: james puede ejecutar como root, y sin contraseña, un binario llamado knife. Ese binario sabe ejecutar código Ruby, y ejecutar código Ruby como root es, en la práctica, ser root.
Vulnerabilidad
Aquí sí hay un CVE, y además con una historia detrás. Son dos piezas.
01 · La puerta trasera de PHP 8.1.0-dev
En marzo de 2021 alguien comprometió el servidor Git de PHP y subió, haciéndose pasar por dos de sus desarrolladores, un commit que insertaba una puerta trasera en el código fuente. El truco: si una petición llega con una cabecera User-Agentt (con dos tes) que empieza por zerodium, el resto de la cabecera se ejecuta como código PHP.
Se detectó en horas y nunca llegó a una versión estable, pero quedó marcado como PHP 8.1.0-dev. Cualquier servidor corriendo esa versión de desarrollo arrastra la puerta, y eso es exactamente lo que publica esta máquina: ejecución remota de código sin autenticar con solo mandar una cabecera.
02 · sudo sobre knife, sin contraseña
Una vez dentro, el usuario james puede ejecutar como root y sin contraseña el binario knife (la herramienta de línea de comandos de Chef). knife sabe ejecutar código Ruby arbitrario, así que ese permiso no es «ejecutar una utilidad»: es ejecutar lo que quieras como root. No hay escalada real que buscar.
Reconocimiento
Barrido completo de puertos contra la víctima, con detección de sistema operativo
| Puerto | Servicio |
| 22 | ssh |
| 80 | http |
Dos puertos abiertos nada más — 22 (SSH) y 80 (HTTP) — y cuatro altos que salen filtrados, que suelen ser ruido de un cortafuegos y no servicios reales. El fingerprinting duda entre un Linux moderno y un MikroTik, señal de que no hay un puerto cerrado limpio con el que afinar.
Con solo SSH y web, y el SSH casi siempre cerrado a cal y canto, todo el peso cae en el puerto 80.

Enumeración
Enumeración de versiones sobre los dos puertos abiertos

Un OpenSSH 8.2p1 y un Apache 2.4.41, ambos de Ubuntu 20.04. La web se titula «Emergent Medical Idea». Miro qué tecnologías monta

Poca cosa a primera vista — fuentes de Google, cdnjs, Cloudflare. Lo interesante no se ve en la página, se ve en las cabeceras, así que tiro de whatweb

Y ahí está lo que lo cambia todo: X-Powered-By: PHP/8.1.0-dev. Una versión de desarrollo de PHP corriendo en producción. Esa cadena, para quien la reconozca, es una bandera roja enorme.
Por completar, una enumeración de directorios

No hay panel oculto ni nada que explotar en la web. No hace falta: la vulnerabilidad no está en lo que sirve la página, sino en el intérprete que la ejecuta.
Explotación
Con la versión en la mano, lo primero es confirmar que esa versión arrastra algo conocido

Ahí está, con nombre y apellidos: PHP 8.1.0-dev — 'User-Agentt' Remote Code Execution. El exploit aprovecha la puerta trasera: manda una cabecera User-Agentt con el prefijo zerodium y a continuación el código PHP a ejecutar. Me traigo el 49933.py y lo lanzo

Le doy la URL y me devuelve una pseudo-consola. Un whoami confirma que estoy ejecutando como james. Pero esto es una webshell: cada comando es una petición HTTP nueva, sin estado, sin TTY. Para trabajar en condiciones necesito una shell de verdad.
Me genero una reverse shell para Linux, la sirvo desde mi máquina con un servidor web y, desde la webshell, la descargo, le doy permisos y la ejecuto
Con el nc a la escucha, la conexión entra

Ahora sí, una shell interactiva como james. La estabilizo y recojo la primera bandera, en su propio home

Escalada de privilegios
Lo primero al aterrizar en un Linux es mirar qué puede ejecutar el usuario con sudo

knife como root y sin contraseña. knife es la herramienta de línea de comandos de Chef, el sistema de gestión de configuración, y no es un binario cualquiera: entre sus funciones sabe ejecutar código Ruby. Lo confirmo en GTFOBins

GTFOBins dice que knife exec -E corre código Ruby, y que si se lanza con sudo los privilegios no se sueltan. El -E es lo que le dice a knife que lo que viene es Ruby a evaluar.
Aquí tuve un pequeño bache: la ficha de knife no traía el comando Ruby ya escrito, así que tuve que mirar aparte cómo se ejecuta un comando desde Ruby. La respuesta estaba en la ficha de ruby del propio GTFOBins

Ruby abre una shell con exec "/bin/sh". Juntando las dos piezas, le paso ese Ruby a knife a través de sudo

Shell como root. Y con el máximo privilegio, la última bandera
Flags
La de usuario, en el home de james
Y la de root, tras el sudo knife
Cómo se arregla
Nada que configurar aquí vale de mucho si el intérprete está comprometido; la clave es no correr software envenenado y no regalar root. Por capas:
- No usar versiones de desarrollo en producción: PHP 8.1.0-dev jamás debió estar en un servidor público. Hay que correr versiones estables y mantenidas, y actualizar; la puerta trasera desapareció en cuanto PHP limpió el repositorio.
- Vigilar la cadena de suministro: este incidente es el ejemplo de manual. Verificar las firmas de lo que se instala y no tirar de ramas de desarrollo arbitrarias.
- No tapar la versión, quitar la causa: ocultar la cabecera X-Powered-By esconde el síntoma pero no cierra la puerta; el exploit funciona igual sin conocer la versión.
- Afinar el sudo: dar knife (o cualquier binario que ejecute código, como Ruby, Python o Perl) como root y sin contraseña equivale a regalar una shell de root. Revisar /etc/sudoers siguiendo GTFOBins y conceder solo lo estrictamente necesario.
Conclusiones
Knife, una maquina sencilla de resolver y de escalar, en mi caso personal, se me complicó no saber que comando ejecutar exactamente con el binario knife, en versiones anteriores de gftobins si pone explicitamente 'exec "/bin/sh"' y no '...', por lo demás todo fácil de conseguir y de intuir.