Está en la página 1de 8

Introducción

Este artículo se centra en proporcionar una guía clara y práctica para


deserializar de forma segura los datos no confiables en sus aplicaciones.

¿Qué es la deserialización?
La serialización es el proceso de convertir algún objeto en un formato de
datos que se puede restaurar más tarde. Las personas a menudo serializan
objetos para guardarlos en el almacenamiento o enviarlos como parte de las
comunicaciones.

La deserialización es el reverso de ese proceso, tomando datos


estructurados de algún formato y reconstruyéndolos en un objeto. Hoy, el
formato de datos más popular para serializar datos es JSON. Antes de eso,
era XML.

Sin embargo, muchos lenguajes de programación ofrecen una capacidad


nativa para serializar objetos. Estos formatos nativos generalmente ofrecen
más funciones que JSON o XML, incluida la personalización del proceso de
serialización.

Desafortunadamente, las características de estos mecanismos de


deserialización nativos se pueden reutilizar para un efecto malicioso cuando
se opera con datos no confiables. Se ha descubierto que los ataques contra
deserializadores permiten ataques de denegación de servicio, control de
acceso y ejecución remota de código (RCE).

Orientación para deserializar objetos


de forma segura
La siguiente guía específica del idioma intenta enumerar metodologías
seguras para deserializar datos en los que no se puede confiar.

PHP
Revisión de WhiteBox
Verifique el uso de la función unserialize () y revise cómo se aceptan los
parámetros externos. Utilice un formato de intercambio de datos estándar
seguro, como JSON (vía json_decode()y json_encode()) si necesita pasar datos
serializados al usuario.

Python
Revisión de BlackBox
Si los datos de tráfico contienen el punto del símbolo .al final, es muy probable
que los datos se hayan enviado en serie.

Revisión de WhiteBox
La siguiente API en Python será vulnerable al ataque de serialización. Código
de búsqueda para el patrón a continuación.

1. Los usos de pickle/c_pickle/_picklecon load/loads:

import pickle
data = """ cos.system(S'dir')tR. """
pickle.loads(data)

1. Usos de PyYAMLcon load:

import yaml
document = "!!python/object/apply:os.system ['ipconfig']"
print(yaml.load(document))

1. Usos de jsonpicklecon encodeo storemétodos.

Java
Las siguientes técnicas son buenas para prevenir ataques contra la
deserialización contra el formato serializable de Java .

Consejos de implementación:

 En su código, anule el ObjectInputStream#resolveClass()método para evitar que las


clases arbitrarias se deserialicen. Este comportamiento seguro se puede incluir en
una biblioteca como SerialKiller .
 Use un reemplazo seguro para el readObject()método genérico como se ve
aquí. Tenga en cuenta que esto aborda los ataques de tipo " billones de risas " al
verificar la longitud de entrada y el número de objetos deserializados.

Revisión de WhiteBox
Tenga en cuenta los siguientes usos de la API de Java para la posible
vulnerabilidad de serialización.

1. XMLdecoder con parámetros externos definidos por el usuario


2. XStreamcon el fromXMLmétodo (la versión xstream <= v1.46 es vulnerable al
problema de serialización)
3. ObjectInputStream con readObject
4. Usos de readObject, readObjectNodData, readResolveoreadExternal
5. ObjectInputStream.readUnshared
6. Serializable
Revisión de BlackBox
Si los datos de tráfico capturados incluyen los siguientes patrones, puede
sugerir que los datos se enviaron en secuencias de serialización Java

 AC ED 00 05 en hexadecimal
 rO0 en Base64
 Content-type encabezado de una respuesta HTTP establecida en application/x-
java-serialized-object

Prevenga la fuga de datos y el Clobbering de campo


confiable
Si hay miembros de datos de un objeto que nunca deberían ser controlados
por los usuarios finales durante la deserialización o expuestos a los usuarios
durante la serialización, deberían declararse como la transientpalabra
clave (sección Protección de información confidencial ).
Para una clase que se define como Serializable, la variable de información
confidencial debe declararse como private transient.
Por ejemplo, la clase myAccount, la variable 'profit' y 'margin' fueron
declaradas como transitorias para evitar ser serializadas:
public class myAccount implements Serializable
{
private transient double profit; // declared transient

private transient double margin; // declared transient


....

Prevenir la deserialización de objetos de dominio


Algunos de los objetos de su aplicación pueden verse obligados a implementar
Serializable debido a su jerarquía. Para garantizar que los objetos de su
aplicación no se puedan deserializar, readObject()se debe declarar un método
(con un finalmodificador) que siempre arroje una excepción:
private final void readObject(ObjectInputStream in) throws
java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}

Endurezca su propio java.io.ObjectInputStream


La java.io.ObjectInputStreamclase se usa para deserializar objetos. Es posible
endurecer su comportamiento subclasificándolo. Esta es la mejor solución si:

 Puedes cambiar el código que hace la deserialización


 Ya sabes qué clases esperas deserializar

La idea general es anular ObjectInputStream.html#resolveClass()) para


restringir qué clases se pueden deserializar.
Debido a que esta llamada ocurre antes de que readObject()se llame a, puede
estar seguro de que no se realizará ninguna actividad de deserialización a
menos que el tipo sea uno que desea permitir.
Un ejemplo simple de esto se muestra aquí,
donde LookAheadObjectInputStreamse garantiza que la clase no deserializará
ningún otro tipo además de la Bicycleclase:
public class LookAheadObjectInputStream extends ObjectInputStream {

public LookAheadObjectInputStream(InputStream inputStream) throws


IOException {
super(inputStream);
}

/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws
IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization
attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Varios miembros de la comunidad han propuesto implementaciones más
completas de este enfoque:

 NibbleSec : una biblioteca que permite la inclusión en listas blancas y negras de las
clases que se pueden deserializar
 IBM : la protección fundamental, escrita años antes de que se imaginaran los
escenarios de explotación más devastadores.
 Clases de Apache Commons IO

Endurezca todo el uso de java.io.ObjectInputStream


con un agente
Como se mencionó anteriormente, la java.io.ObjectInputStreamclase se usa
para deserializar objetos. Es posible endurecer su comportamiento
subclasificándolo. Sin embargo, si no posee el código o no puede esperar un
parche, java.io.ObjectInputStreamla mejor solución es usar un agente para
tejerlo .
El cambio global ObjectInputStreamsolo es seguro para incluir en la lista negra
los tipos maliciosos conocidos, porque no es posible saber para todas las
aplicaciones cuáles son las clases esperadas que se
deserializarán. Afortunadamente, hoy en día se necesitan muy pocas clases
en la lista negra para estar a salvo de todos los vectores de ataque conocidos.
Es inevitable que se descubran más clases de "gadgets" que puedan ser
abusadas. Sin embargo, hay una increíble cantidad de software vulnerable
expuesto hoy, que necesita una solución. En algunos casos, "corregir" la
vulnerabilidad puede implicar rediseñar los sistemas de mensajería y romper
la compatibilidad con versiones anteriores a medida que los desarrolladores
avanzan hacia la no aceptación de objetos serializados.

Para habilitar estos agentes, simplemente agregue un nuevo parámetro JVM:


-javaagent:name-of-agent.jar
Los agentes que toman este enfoque han sido liberados por varios miembros
de la comunidad:

 rO0 por seguridad de contraste

Un enfoque similar, pero menos escalable, sería parchar y arrancar


manualmente el ObjectInputStream de su JVM. La orientación sobre este
enfoque está disponible aquí .

.Net CSharp
Revisión de WhiteBox
Busque en el código fuente los siguientes términos:

1. TypeNameHandling
2. JavaScriptTypeResolver

Busque cualquier serializador donde el tipo sea establecido por una variable
controlada por el usuario.

Revisión de BlackBox
Busque el siguiente contenido codificado en base64 que comienza con:
AAEAAAD/////
Busque contenido con el siguiente texto:

1. TypeObject
2. $type:

Precauciones generales
No permita que el flujo de datos defina el tipo de objeto para el que se
deserializará el flujo. Puede evitar esto, por ejemplo,
utilizando DataContractSerializero XmlSerializersi es posible.
Dónde JSON.Netse usa, asegúrese de TypeNameHandlingque solo esté
configurado en None.
TypeNameHandling = TypeNameHandling.None
Si se JavaScriptSerializerva a usar, no lo use con a JavaScriptTypeResolver.
Si debe deserializar flujos de datos que definen su propio tipo, entonces
restrinja los tipos que pueden deserializarse. Se debe tener en cuenta que esto
sigue siendo riesgoso ya que muchos tipos .Net nativos son potencialmente
peligrosos en sí mismos. p.ej
System.IO.FileInfo
FileInfo Los objetos que hacen referencia a archivos realmente en el servidor
pueden, cuando se deserializan, cambiar las propiedades de esos archivos,
por ejemplo, a solo lectura, creando un posible ataque de denegación de
servicio.
Incluso si ha limitado los tipos que se pueden deserializar, recuerde que
algunos tipos tienen propiedades
riesgosas. System.ComponentModel.DataAnnotations.ValidationException, por
ejemplo, tiene una propiedad Valuede tipo Object. Si este tipo es el tipo
permitido para la deserialización, un atacante puede establecer
la Valuepropiedad en cualquier tipo de objeto que elija.
Se debe evitar que los atacantes dirijan el tipo que se instanciará. Si esto es
posible, entonces incluso DataContractSerializero XmlSerializerpuede ser
subvertido, por ejemplo
// Action below is dangerous if the attacker can change the data in the
database
var typename = GetTransactionTypeFromDatabase();

var serializer = new DataContractJsonSerializer(Type.GetType(typename));

var obj = serializer.ReadObject(ms);


La ejecución puede ocurrir dentro de ciertos tipos .Net durante la
deserialización. Crear un control como el que se muestra a continuación no es
efectivo.
var suspectObject = myBinaryFormatter.Deserialize(untrustedData);

//Check below is too late! Execution may have already occurred.


if (suspectObject is SomeDangerousObjectType)
{
//generate warnings and dispose of suspectObject
}
Para BinaryFormattery JSON.Netes posible crear una forma más segura de
control de lista blanca utilizando una costumbre SerializationBinder.
Trate de mantenerse actualizado sobre los dispositivos de deserialización
inseguros .Net conocidos y preste especial atención donde dichos tipos
pueden ser creados por sus procesos de deserialización. Un deserializador
solo puede crear instancias de tipos que conoce .

Intente mantener cualquier código que pueda crear dispositivos potenciales


separados de cualquier código que tenga conectividad a Internet. Como
ejemplo System.Windows.Data.ObjectDataProviderutilizado en las aplicaciones
WPF es un dispositivo conocido que permite la invocación de métodos
arbitrarios. Sería arriesgado tener una referencia a este ensamblado en un
proyecto de servicio REST que deserializa datos no confiables.

Gadgets .NET RCE conocidos


 System.Configuration.Install.AssemblyInstaller
 System.Activities.Presentation.WorkflowDesigner
 System.Windows.ResourceDictionary
 System.Windows.Data.ObjectDataProvider
 System.Windows.Forms.BindingSource
 Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvid
er
 System.Data.DataViewManager, System.Xml.XmlDocument/XmlDataDocument
 System.Management.Automation.PSObject

Métodos agnósticos del lenguaje


para deserializar de forma segura
Usar formatos de datos alternativos
Se logra una gran reducción del riesgo al evitar los formatos de (des)
serialización nativos. Al cambiar a un formato de datos puro como JSON o
XML, disminuye la posibilidad de que la lógica de deserialización
personalizada se reutilice para fines maliciosos.

Muchas aplicaciones se basan en un patrón de objeto de transferencia de


datos que implica la creación de un dominio separado de objetos para la
transferencia de datos de propósito explícito. Por supuesto, todavía es posible
que la aplicación cometa errores de seguridad después de analizar un objeto
de datos puro.

Deserializar solo datos firmados


Si la aplicación sabe antes de la deserialización qué mensajes deberán
procesarse, podría firmarlos como parte del proceso de serialización. La
aplicación podría elegir no deserializar ningún mensaje que no tuviera una
firma autenticada.

Herramientas de mitigación /
bibliotecas
 Biblioteca de deserialización segura de Java
 SWAT (Entrenador de aplicaciones de la lista blanca de serie)
 NotSoSerial

Herramientas de detección
 Hoja de trucos de deserialización de Java dirigida a probadores de pluma
 Una herramienta de prueba de concepto para generar cargas útiles que aprovechan
la deserialización de objetos Java insegura.
 Juegos de herramientas de deserialización de Java
 Herramienta de deserialización de Java
 Generador de carga útil .Net
 Extensión Burp Suite
 Biblioteca de deserialización segura de Java
 Serianalyzer es un analizador de bytecode estático para deserialización
 Generador de carga útil
 Android Java Deserialization Vulnerability Tester
 Burp Suite Extension
o JavaSerialKiller
o Escáner de deserialización de Java
o Eructo-ysoserial
o SuperSerial
o SuperSerial-Active

Referencias
 Java-Deserialization-Cheat-Sheet
 Deserialización de datos no confiables
 Ataques de deserialización de Java - Día alemán OWASP 2016
 AppSecCali 2015 - Encurtidos encurtidos
 FoxGlove Security - Anuncio de vulnerabilidad
 Hoja de trucos de deserialización de Java dirigida a probadores de pluma
 Una herramienta de prueba de concepto para generar cargas útiles que aprovechan
la deserialización de objetos Java insegura.
 Juegos de herramientas de deserialización de Java
 Herramienta de deserialización de Java
 Extensión Burp Suite
 Biblioteca de deserialización segura de Java
 Serianalyzer es un analizador de bytecode estático para deserialización
 Generador de carga útil
 Android Java Deserialization Vulnerability Tester
 Burp Suite Extension
o JavaSerialKiller
o Escáner de deserialización de Java
o Eructo-ysoserial
o SuperSerial
o SuperSerial-Active
 .Red
o Alvaro Muñoz: serialización .NET: detección y defensa de puntos finales
vulnerables
o James Forshaw - Black Hat USA 2012 - ¿Eres mi tipo? Rompiendo cajas de arena
.net a través de la serialización
o Jonathan Birch BlueHat v17 - Contenido peligroso - Asegurar la deserialización
de .Net
o Alvaro Muñoz y Oleksandr Mirosh - Viernes 13: Atacando a JSON - AppSecUSA
2017

También podría gustarte