Deserialización Insegura PHP

Pagina Vulnerable Deserialización Insegura en PHP

Si nosotros por ejemplo tenemos este codigo de PHP como una pagina por ejemplo:

index.php

<?php
// Clase vulnerable: al deserializar el objeto se ejecuta el comando almacenado en $cmd
class Vulnerable {
    public $cmd;

    public function __construct($cmd) {
        $this->cmd = $cmd;
    }

    public function __destruct() {
        system($this->cmd);
    }
}

// Función para verificar si las credenciales son correctas
function authenticate($username, $password) {
    $valid_users = [
        'admin' => 'admin',
        'user' => 'user'
    ];

    if (isset($valid_users[$username]) && $valid_users[$username] === $password) {
        return true;
    }
    return false;
}

// Si el formulario es enviado
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Recuperamos las credenciales del formulario
    $username = $_POST['username'] ?? '';
    $password = $_POST['password'] ?? '';

    // Si las credenciales son correctas
    if (authenticate($username, $password)) {
        // Creamos un payload malicioso (cookie) solo para usuarios válidos
        $cmd = "echo 'Comando ejecutado exitosamente';";  // Cambia esto con el comando que desees
        $vulnerable_object = new Vulnerable($cmd);
        $serialized_object = serialize($vulnerable_object);
        $encoded_payload = base64_encode($serialized_object);

        // Establecemos la cookie con el payload
        setcookie('session', $encoded_payload, time() + 3600, "/"); // La cookie durará 1 hora

        // Redirigimos al usuario a panel.php después del login
        header('Location: panel.php?username=' . urlencode($username));
        exit;
    } else {
        echo "<p>Credenciales incorrectas. Por favor, inténtalo de nuevo.</p>";
    }
}
?>

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login - Deserialización Insegura</title>
</head>
<body>
    <h1>Login de Usuario</h1>

    <!-- Formulario de login -->
    <form method="POST">
        <label for="username">Nombre de usuario:</label>
        <input type="text" id="username" name="username" required><br><br>

        <label for="password">Contraseña:</label>
        <input type="password" id="password" name="password" required><br><br>

        <button type="submit">Iniciar sesión</button>
    </form>
</body>
</html>

Vemos que no valida la entrada que se serializa y la deserializa lo que venga de forma insegura, ya que no tiene ninguna medida de seguridad como por ejemplo una implementacion de JWT, si entramos a esta pagina veremos lo siguiente:

El usuario por defecto sera el siguiente:

Ingresamos las credenciales y abriremos BurpSuite para recargar la pagina con la sesion iniciada del usuario user y veremos lo siguiente en la peticion con BurpSuite:

Peticion de BurpSuite

Vemos que la serializacion esta en session= por lo que tendremos que reemplazar su contenido, por otro codigo serializado con el comando que queramos ejecutar.

Generar Payload Serializado en Base64

Nos crearemos un script en bash para generar codigos serializados:

exploitSerial.sh

Ahora lo ejecutaremos de la siguiente forma:

Info:

Enviar Payload al servidor

Ahora este resultado tendremos que pegarlo en la peticion donde session= quedando de la siguiente forma:

Ahora si enviamos la peticion veremos lo siguiente en la pagina:

Vemos que algo ha sido modificado, por lo que podemos deducir que si ha funcionado correctamente.

Vamos a irnos al servidor para comprobar que ha funcionado la deserializacion y que se ha ejecutado de forma correcta en el servidor:

Vemos que ha funcionado, por lo que podremos generar payloads y ejecutar codigo de forma remota.

Last updated