Skip to main content
Explotación de la deserialización en PHP

Explotación de la deserialización en PHP

La explotación de objetos serializados en php es una vulnerabilidad bastante común y a través de la cual se puede, entre otras, conseguir acceso a un servidor que utilice este lenguaje

Bienvenidos a un nuevo post en ByteMind. En el caso de hoy vamos a tratar el tema de la explotación de objetos serializados en php, una vulnerabilidad bastante común (por suerte o por desgracia) y a través de la cual se puede, entre otras, conseguir acceso a un servidor que utilice este lenguaje de programación en su sitio web, pero antes de nada vamos a ver que es la serialización de objetos en PHP.

 

¿Qué es la serialización de objetos?

En programación, la serialización de objetos consiste en un proceso de codificación de un objeto en un medio de almacenamiento (como puede ser un fichero o un buffer de memoria) con el fin de transmitir el mismo a través de una conexión de red como una serie de bytes o en un formato más legible humanamente, como puede ser XML o JSON. 

Esta serie de bytes o el formato, pueden ser utilizados para crear un objeto nuevo, idéntico al original, incluido su estado interno. La serialización es un mecanismo amplicamente utilizado para transportar objetos a través de la red, para hacer persistente mediante su almacenamiento en un fichero, un buffer o una base de datos o para distribuir objetos idénticos entre una o varias aplicaciones o localizaciones.

Por otro lado, la deserialización sería el proceso contrario, es decir, cuando el objeto serializado se lee de un archivo o transmisión de red se convierte nuevamente en el objeto original.

Las vulnerabilidades por deserialización inseguras ocurren cuando las aplicaciones realizan este proceso sin el filtrado adecuado, por lo que un atacante podría manipular estos objetos o enviar los suyos propios con la intención de conseguir la ejecución de software malicioso o de obtener datos sensibles de la aplicación.

 

Serialización de objetos en PHP

Para comprender como se explotan este tipo de vulnerabilidades, en primer lugar, vamos a explicar como realiza PHP este proceso de serializado y deserializado de objetos.

Serializar un objeto

Para realizar el proceso de serializado de un objeto en PHP se utiliza la función serialize()

Vamos a verlo con un ejemplo, en el siguiente fragmento de código serializaremos el objeto User:

Ejecutando el anterior fragmento de código obtendremos un objeto serializado como el siguiente:

 

Deserializar un objeto

Cuando se necesite operar con un objeto serializado se hará uso de la función unserialize() para obtener el objeto original.

Vamos a verlo con un ejemplo:

El resultado del anterior fragmento de código sería el siguiente:

 

Estructura de una cadena serializada

La estructura básica de una cadena serializada es “tipo de datos: datos”, y los tipos de dato pueden ser los siguientes:

b -> booleano

i -> integer

d -> float

s -> string

a -> array

O -> objeto

 

Por lo tanto podemos ver que nuestra cadena serializada representa un objeto de la clase “Usuario” con dos propiedades. 

La primera propiedad tiene el nombre “username” y el valor “bytemind” y la segunda propiedad tiene el nombre “status” y el valor “not admin”.

 

¿Cómo funciona el deserializado de PHP internamente?

Para ver y comprender en detalle este tipo de vulnerabilidades vamos a explicar como funciona este proceso internamente.

Métodos mágicos en PHP

Los métodos mágicos en PHP son funciones con ciertas propiedades, puede ver más acerca de ello en la documentación oficial.

En este caso vamos a tratar aquellos métodos que son relevantes para nosotros que son __wakeup() y __destruct(). Si la clase del objeto serializado implementa cualquiera de estos dos métodos, estos serán llamados automáticamente cuando se trate de deserializar un objeto.

Veamos su ciclo de vida para comprender este proceso.

 

Ciclo de vida

Paso 1: Instanciar el objeto

La instanciación es el proceso en el cual un programa crea una instancia de una clase en la memoria. Ahora la función userialize() tomará la cadena serializada que especifica la clase y las propiedades del objeto y creará una copia del objeto serializado originalmente.

Después, buscará la función llamada __wakeup() y ejecutará el código de dicha función. La función __wakeup() se encargará de reconstruir cualquier recurso que pudiese tener el objeto.

 

Paso 2: El programa utiliza el objeto

El programa opera sobre el objeto y realiza las acciones oportunas necesarias para su funcionamiento.

 

Paso 3: Destrucción del objeto

Por último, cuando ya no existe ninguna referencia a la instancia del objeto serializado, se llama a la función __destruct() para limpiar el objeto.

 

Explotar la vulnerabilidad de deserialización en PHP

Cuando se trata de deserealizar un objeto, controlas las propiedades del mismo. También es posible secuestrar el flujo de una aplicación controlando los valores que se pasan a métodos que se ejecutan automáticamente como los vistos anteriormente, __wakeup() y __destruct().

A esto se le llama inyección de objetos en PHP, y puede conducir a diferentes vulnerabilidades como puede ser la manipulación de variables, RCE, SQLi, etc.

Vamos a ver algún ejemplo de como se podría explotar esta vulnerabilidad.

 

Controlar el valor de las variables

Por ejemplo, supongamos que un portal web envía en la cookie el siguiente valor serializado:

Podríamos por ejemplo aprovechar una vulnerabilidad para manipular el valor de ciertas variables como vemos en el siguiente ejemplo:

Enviaremos la cookie con nuestro valor serializado una vez modificado el estado de “not admin” a “admin” con la intención de conseguir permisos de admin en la aplicación.

 

Explotar un RCE

También es posible lograr un RCE (Remote Code Execution) mediante la inyección de objetos PHP. Vamos a verlo con un ejemplo y utilizaremos el siguiente código vulnerable (obtenido de OWASP):

En este ejemplo es posible conseguir un RCE debido a que el objeto se pasa directamente a unserialize sin llegar a filtrar el contenido existente en el mismo. Además, la clase Example2 tiene la función mágica __wakeup() ejecuta eval() en la entrada proporcionada por el usuario.

Para explotar este RCE, simplemente tiene que configurar su cookie de datos en un objeto Example2 serializado con la propiedad $hook configurada en cualquier código PHP que desee.

En este ejemplo, un atacante podría realizar un ataque enviando una petición como la siguiente:

Donde el parámetro data de la cookie ha sido generado por el siguiente script:

Una vez enviada la cadena generada provocará que se ejecute el código phpinfo() en la máquina. Una vez que pase el objeto serializado al programa sucederá lo siguiente:

  1. Se envía un objeto Example2 serializado al programa mediante la cookie data.
  2. El programa llamará a unserialize() en la cookie de data
  3. A continuación, la función unserialize() creará una instancia de un nuevo objeto Example2
  4. Debido a que tiene implementado el método __wakeup(), ejecutará el mismo
  5. La función __wakeup() buscará la propiedad $hook del objeto, y si no es nula, ejecutará el código eval($hook) ejecutando nuestro código phpinfo()
  6. Se logra realizar el RCE

 

Conclusiones

Como conclusión se ha podido observar que si se puede controlar la cadena serializada se puede controlar el objeto que se genera en el mismo.

Si dicho objeto no se desinfecta antes de la deserialización, es posible que se produzca la explotación de una vulnerabilidad de inyección de objetos PHP.

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *