Fundamentos de Serialización en PHP y Análisis de Vulnerabilidades de Deserialización

Preparación del Entorno de Laboratorio

Para analizar estos conceptos de forma práctica y segura, es aconsejable aislar el entorno mediante contenedores. A continuación, se detalla el despliegue utilizando Docker:

docker pull mcc0624/ser:1.8
docker run -d -p 8888:80 mcc0624/ser:1.8

Paradigmas de Programación: Estructurado vs. Orientado a Objetos

En el desarrollo de software, la programación estructurada (o procedimental) se centra en una secuencia lineal de instrucciones y funciones para resolver un problema. Por el contrario, la Programación Orientada a Objetos (POO) modela el software mediante entidades que encapsulan tanto el estado (datos) como el comportamiento (métodos), promoviendo la modularidad y la reutilización.

Conceptos Fundamentales de Clases y Objetos

Una clase actúa como un plano o plantilla que define las propiedades y métodos comunes. Un objeto es una instancia materializada de dicha clase en memoria.

Instanciación y Modificadores de Acceso

Los modificadores de acceso (public, private, protected) dictan la visibilidad de los atributos y métodos. A continuación, se preesnta una implementación reestructurada:

<?php
class SystemUser {
    public $username;
    private $passwordHash;
    protected $accessLevel;

    public function __construct($user, $hash, $level) {
        $this->username = $user;
        $this->passwordHash = $hash;
        $this->accessLevel = $level;
    }

    public function authenticate() {
        return "Autenticando al usuario: " . $this->username;
    }
}

$admin = new SystemUser('admin_root', 'sha256_hashed', 9);
print_r($admin);
echo $admin->authenticate();
?>

Herencia de Clases

Las subclases heredan propiedades y métodos de una clase base, permitiendo la extensión de funcionalidades:

<?php
class BaseEmployee {
    public $name = 'Carlos';
    protected $department = 'IT';
    private $salary = 5000;
}

class Manager extends BaseEmployee {
    public function getDetails() {
        return $this->name . " - " . $this->department;
    }
}

$mgr = new Manager();
echo $mgr->getDetails();
?>

Mecanismos de Serialización en PHP

La serialización convierte el estado de una variable (como un objeto o un array) en una representación de cadena de bytes, facilitando su almacenamiento o transmisión. En PHP, esto se logra mediante la función serialize().

Representación de Tipos de Datos

<?php
$dataSet = ['node1', 'node2', 'node3'];
echo serialize($dataSet);
// Salida: a:3:{i:0;s:5:"node1";i:1;s:5:"node2";i:2;s:5:"node3";}
?>

Serialización de Objetos y Visibilidad

La visibilidad de los atributos altera la cadena seiralizada resultante. Los atributos privados y protegidos incluyen caracteres nulos (%00) en la cadena cruda.

<?php
class DatabaseConfig {
    public $host = 'localhost';
    private $credentials = 'root:pass';
    protected $port = 3306;
}

$config = new DatabaseConfig();
echo urlencode(serialize($config));
?>

En la salida codificada, las propiedades privadas se prefijan con %00DatabaseConfig%00 y las protegidas con %00*%00.

Proceso de Deserialización

La función unserialize() toma la cadena serializada y reconstruye la variable original. Es crucial comprender que los valores deserializados sobrescriben los valores predeterminados definidos en la clase.

<?php
class SessionData {
    public $token = 'default_token';
    public $isActive = false;
}

$maliciousPayload = 'O:11:"SessionData":2:{s:5:"token";s:11:"admin_token";s:8:"isActive";b:1;}';
$restoredSession = unserialize($maliciousPayload);
var_dump($restoredSession);
?>

El objeto resultante tendrá 'admin_token' y true, ignorando por completo los valores por defecto declarados en la estructura de la clase.

Vulnerabilidades de Deserialización

Las fallas de seguridad surgen cuando la aplicación deserializa datos controlados por el usuario sin la validación adecuada. Aunque la deserialización por sí sola no ejecuta métodos arbitrarios, puede manipular el estado del objeto para desencadenar comportamientos no deseados cuando los métodos mágicos o métodos regulares son invocados posteriormente.

Evasión del Método Mágico __wakeup()

Un vector de ataque clásico implica la vulnerabilidad CVE-2016-7124, que permite omitir la ejecución del método __wakeup() manipulando el recuento de propiedades en la cadena serializada.

<?php
class SecureVault {
    public $secretKey = 'initial_value';

    public function __wakeup() {
        die('Acceso denegado: Solicitud no válida.');
    }
}
?>

La cadena serializada legítima para esta clase sería:

O:11:"SecureVault":1:{s:9:"secretKey";s:13:"initial_value";}

Para eludir la restricción impuesta por __wakeup(), el atacante incrementa el número declarado de propiedades (de 1 a 2 o más). Esta inconsistencia hace que el motor de PHP omita la llamada al método mágico durante la reconstrucción del objeto.

Payload modificado:

O:11:"SecureVault":2:{s:9:"secretKey";s:13:"initial_value";}

Al inyectar esta cadena alterada, el objeto se instanciará sin ejecutar el bloque de código defensivo, permitiendo la explotación de la lógica subyacente de la aplicación.

Etiquetas: PHP deserialización Serialización POO InyecciónDeObjetos

Publicado el 7-4 00:28