La serialización de Java es un mecanismo para transformar un objeto en un flujo de bytes. La deserialización de Java es exactamente al revés y nos permite recrear un objeto a partir de un flujo de bytes. La serialización de Java—y más específicamente la deserialización en Java-también se conoce como»el regalo que sigue dando». Esto guarda relación con las numerosas cuestiones de seguridad y otros problemas que ha producido a lo largo de los años.,
¿Qué es la serialización en Java?
en Java, creamos objetos. Estos objetos viven en la memoria y son eliminados por el recolector de basura una vez que ya no se utilizan. Si queremos transferir un objeto, por ejemplo, almacenarlo en un disco o enviarlo a través de una red, necesitamos transformarlo en un flujo de bytes. Para hacer esto, la clase de ese objeto necesita implementar la interfaz Serializable
. La serialización es convertir el estado de un objeto en un flujo de bytes. Esta secuencia de bytes no contiene el código real.,
¿Qué es la serialización en Java?
la deserialización es precisamente lo opuesto a la serialización. Con la deserialización, usted tiene un flujo de bytes y de volver a crear el objeto en el mismo estado que cuando se serializa ella. Esto significa que usted necesita tener la definición real del objeto para lograr la recreación.
¿cómo funciona la serialización Java?
La serialización Java utiliza la reflexión para raspar todos los datos de los campos del objeto que necesitan ser serializados. Esto incluye campos privados y finales., Si un campo contiene un objeto, ese objeto se serializa recursivamente. A pesar de que puede tener getters y setters, estas funciones no se utilizan cuando se serializa un objeto en Java.
¿Cómo Java deserialización de trabajo?
cuando se deserializa un flujo de bytes de nuevo a un objeto, no utiliza el constructor. Crea un objeto vacío y utiliza la reflexión para escribir los datos en los campos. Al igual que con la serialización, también se incluyen los campos privados y finales.
¿qué es una vulnerabilidad Java deserialize?,
Una vulnerabilidad de deserialización de Java es una vulnerabilidad de seguridad que ocurre cuando un usuario malicioso intenta insertar un objeto serializado modificado en el sistema que eventualmente compromete el sistema o sus datos. Piense en la ejecución de código arbitrario que se puede activar al deserializar un objeto serializado. Para explicar mejor las vulnerabilidades de Java deserialize, primero necesitamos explorar cómo funciona la deserialización en Java.
Explicando Java deserializar vulnerabilidades
Un objeto serializado en Java es una matriz de bytes con la información del estado., Contiene el nombre del objeto al que se refiere y los datos del campo. Si observa un objeto serializado almacenado con un editor hexadecimal, puede encerrar y manipular la información rápidamente.
ya sabemos que la deserialización de Java no utiliza el constructor para crear un objeto, sino que utiliza la reflexión para cargar los campos. Esto significa que cualquier comprobación de validación realizada en el constructor nunca se llama al recrear el objeto. Puede pensar en comprobaciones como la fecha de inicio antes de la fecha de finalización al describir un período., Al deserializar un objeto Java, este nuevo objeto puede tener un estado no válido.
veamos el siguiente ejemplo de Java deserializar vulnerabilidad donde podemos serializar un objeto de una clase serializable ValueObject
:
Al leer el archivo ValueObject.ser
que contiene el objeto serializado con un editor hexadecimal el resultado es este.
Ahora que fácilmente se puede manipular la cadena de valor. A continuación me cambio de Hi
a Hallo
.,
Cuando deserializar el ajustado archivo binario, nos enteramos de que el objeto del value
cambiado. También vemos que la marca de tiempo no cambió, demostrando que el constructor nunca es llamado. Por lo tanto, si una aplicación acepta objetos serializados, es relativamente fácil moderar con los valores. Al alterar los objetos serializados, podemos crear objetos inválidos, interferir con la integridad de los datos, o incluso peor.,
ejecución arbitraria de código, gadgets y cadenas
manipular los datos de un objeto ya es dañino. Sin embargo, esto también puede conducir a la ejecución de código si el conjunto correcto de objetos se deserializa. Para explicar esto primero tengo que explicar gadgets y cadenas.
Gadgets
Un gadget—como lo usa Lawrence & Frohoff en su charla Marschalling Pickle en AppSecCali 2015—es una clase o función que ya tiene código ejecutable existente presente en el proceso vulnerable. Este código ejecutable existente se puede reutilizar con fines maliciosos., Si observamos objetos serializables en Java, algunos métodos mágicos, como el método privado readObject()
, se llaman reflectivamente cuando se deserializan.
veamos el gadget simplificado a continuación:
Esta clase de gadget anula el método predeterminado readObject
. Como resultado, cada vez que un objeto de clase Gadget se deserializa, se ejecuta el comando objeto Runnable
. Cuando una clase de comando se parece al ejemplo siguiente, es fácil manipular este objeto serializado y realizar la inyección de código.,
además, tenga en cuenta que si una aplicación acepta objetos serializados, el objeto se deserializa primero antes de ser lanzado al tipo deseado. Esto significa que incluso si falla el casting, la deserialización ya se ha completado y se ejecuta el método readObject()
.
ataque de deserialización de cadenas de gadgets
un ataque de deserialización típico consiste en una cadena de gadgets ingeniosamente diseñada. Un atacante busca un gadget que sea utilizable para lanzar un ataque y encadena varias ejecuciones que terminan con la ejecución de código arbitrario, por ejemplo.,
en nuestro ejemplo:
Gadget -> readObject() -> command.run() -> Runtime.getRuntime().exec()
para un ejemplo más real, eche un vistazo a la implementación de java.util.HashMap
. Esta clase tiene una implementación personalizada del método readObject()
que activa la función hashcode()
de cada clave.
Bibliotecas
es bueno saber que cualquier gadget cadenas están disponibles en la aplicación, no está relacionada con su código., Debido a que importamos mucho código de bibliotecas y frameworks, el número de clases importadas por sus dependencias (transitivas) influye en la posibilidad de ciertas cadenas de gadgets. Aunque crear una cadena de gadgets tan maliciosos es muy duro y laborioso, vulnerabilidades de deserialización de Java son un riesgo de seguridad genuino y peligroso.
¿cómo prevenir una vulnerabilidad de Java deserialize?
la mejor manera de prevenir una vulnerabilidad de Java deserialize es prevenir la serialización de Java en general. Si su aplicación no acepta objetos serializados en absoluto, no puede hacerle daño.,
sin embargo, si necesita implementar la interfaz Serializable debido a la herencia, puede anular el readObject()
, como se ve a continuación, para evitar la deserialización real.
si su aplicación se basa en objetos serializados, puede considerar inspeccionar su ObjectInputStream
antes de deserializar. Una biblioteca que puede ayudarle con esto es la biblioteca Apache Commons IO. Esta biblioteca proporciona un ValidatedObjectInputStream
donde puede permitir explícitamente los objetos que desea deserializar. Ahora usted evitar que inesperado tipos se deserializa a todos.,
una herramienta como ysoserial también es extremadamente útil para encontrar vulnerabilidades de Java deserialize en su código. Es una herramienta que genera carga útil para descubrir cadenas de gadgets en bibliotecas Java comunes que pueden, en las condiciones adecuadas, explotar aplicaciones Java que realizan deserialización insegura de objetos.
tenga en cuenta que las vulnerabilidades de deserialización de Java no son exclusivas de la implementación de serialización personalizada de Java. Aunque este artículo simplemente se centra en esta parte, las mismas vulnerabilidades existen en los marcos de serialización o de clasificación que manejan esto por usted., Si hay un framework que mágicamente crea POJO’s a partir de XML, JSON, yaml o formatos similares, probablemente use reflection de la misma manera que se describió anteriormente. Esto significa que existen los mismos problemas.