Basic Java Deserialization with ObjectInputStream readObject
Reading time: 6 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
Bu POST'ta java.io.Serializable
kullanarak bir örnek açıklanacak ve neden readObject()
'ın geçerli bir akış saldırgan kontrolündeyse son derece tehlikeli olabileceği anlatılacak.
Serializable
Java Serializable
arayüzü (java.io.Serializable
), sınıflarınızın serileştirilmesi ve serileştirilmesinin geri alınması için uygulaması gereken bir işaretçi arayüzüdür. Java nesne serileştirmesi (yazma) ObjectOutputStream
ile yapılır ve serileştirilmenin geri alınması (okuma) ObjectInputStream
ile yapılır.
Hatırlatma: Serileştirilmenin geri alınması sırasında hangi yöntemler örtük olarak çağrılır?
readObject()
– sınıfa özgü okuma mantığı (eğer uygulanmışsa ve özel ise).readResolve()
– serileştirilen nesneyi başka bir nesne ile değiştirebilir.validateObject()
–ObjectInputValidation
geri çağırmaları aracılığıyla.readExternal()
–Externalizable
uygulayan sınıflar için.- Yapıcılar çalıştırılmaz – bu nedenle gadget zincirleri yalnızca önceki geri çağırmalara dayanır.
O zincirdeki herhangi bir yöntem, saldırgan kontrolündeki verileri (komut yürütme, JNDI aramaları, yansıma vb.) çağırırsa, serileştirme rutini bir RCE gadget'ına dönüşür.
Serileştirilebilir olan bir Person sınıfı ile bir örneğe bakalım. Bu sınıf readObject fonksiyonunu aşırı yükler, böylece bu sınıfın herhangi bir nesnesi serileştirildiğinde bu fonksiyon çalıştırılacaktır.
Örnekte, Person sınıfının readObject fonksiyonu, evcil hayvanının eat()
fonksiyonunu çağırır ve bir Köpek'in eat()
fonksiyonu (bir sebepten dolayı) calc.exe'yi çağırır. Bu hesap makinesini çalıştırmak için bir Person nesnesini nasıl serileştirip serileştireceğimizi göreceğiz:
Aşağıdaki örnek https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649 adresinden alınmıştır.
import java.io.Serializable;
import java.io.*;
public class TestDeserialization {
interface Animal {
public void eat();
}
//Class must implements Serializable to be serializable
public static class Cat implements Animal,Serializable {
@Override
public void eat() {
System.out.println("cat eat fish");
}
}
//Class must implements Serializable to be serializable
public static class Dog implements Animal,Serializable {
@Override
public void eat() {
try {
Runtime.getRuntime().exec("calc");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("dog eat bone");
}
}
//Class must implements Serializable to be serializable
public static class Person implements Serializable {
private Animal pet;
public Person(Animal pet){
this.pet = pet;
}
//readObject implementation, will call the readObject from ObjectInputStream and then call pet.eat()
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException {
pet = (Animal) stream.readObject();
pet.eat();
}
}
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(String[] args) throws Exception {
// Example to call Person with a Dog
Animal animal = new Dog();
Person person = new Person(animal);
GeneratePayload(person,"test.ser");
payloadTest("test.ser");
// Example to call Person with a Cat
//Animal animal = new Cat();
//Person person = new Person(animal);
//GeneratePayload(person,"test.ser");
//payloadTest("test.ser");
}
}
Sonuç (klasik senaryo)
Bu çok temel örnekte görüldüğü gibi, buradaki “zayıflık” readObject() metodunun başka bir saldırgan kontrolündeki kodu çağırmasından kaynaklanmaktadır. Gerçek dünyadaki gadget zincirlerinde, dış kütüphanelerde (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, vb.) bulunan binlerce sınıf kötüye kullanılabilir – saldırganın yalnızca bir erişilebilir gadget'a ihtiyacı vardır.
2023-2025: Java deserialization saldırılarında neler yeni?
- 2023 – CVE-2023-34040:
checkDeserExWhen*
bayrakları etkinleştirildiğinde Spring-Kafka hata kayıt başlıklarının deserialization'ı, saldırgan tarafından yayımlanan konulardan keyfi gadget inşasına izin verdi. 3.0.10 / 2.9.11'de düzeltildi. ¹ - 2023 – CVE-2023-36480: Aerospike Java istemcisi güvenilir sunucu varsayımı kırıldı – kötü niyetli sunucu yanıtları, istemci tarafından deserialized edilen serileştirilmiş yükler içeriyordu → RCE. ²
- 2023 – CVE-2023-25581:
pac4j-core
kullanıcı profili öznitelik ayrıştırması{#sb64}
ile başlayan Base64 blob'larını kabul etti veRestrictedObjectInputStream
olmasına rağmen bunları deserialized etti. 4.0.0 veya üstü sürüme yükseltin. - 2023 – CVE-2023-4528: JSCAPE MFT Manager Service (port 10880) XML kodlu Java nesnelerini kabul etti ve bu da root/SYSTEM olarak RCE'ye yol açtı.
- 2024 – Eski filtreleri atlayan Hibernate5, TomcatEmbed ve SnakeYAML 2.x sınıflarını içeren birden fazla yeni gadget zinciri ysoserial-plus(mod) eklendi.
Uygulamanız gereken modern önlemler
- JEP 290 / Serileştirme Filtreleme (Java 9+) Sınıfların bir izin listesi veya yasak listesi ekleyin:
# Sadece DTO'larınızı ve java.base'ı kabul edin, diğer her şeyi reddedin
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"
Programatik örnek:
var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
- JEP 415 (Java 17+) Bağlama Özel Filtre Fabrikaları – her yürütme bağlamı için (örneğin, her RMI çağrısı, her mesaj kuyruğu tüketicisi) farklı filtreler uygulamak için bir
BinaryOperator<ObjectInputFilter>
kullanın. - Ham
ObjectInputStream
'i ağda açmayın – kod yürütme anlamı taşımayan JSON/Binary kodlamalarını tercih edin (JacksonDefaultTyping
devre dışı bırakıldıktan sonra, Protobuf, Avro, vb.). - Derinlikte Savunma sınırları – maksimum dizi uzunluğu, derinlik, referanslar ayarlayın:
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
- Sürekli gadget taraması – tehlikeli bir gadget erişilebilir hale gelirse inşaatı başarısız kılmak için CI'nizde
gadget-inspector
veyaserialpwn-cli
gibi araçları çalıştırın.
Güncellenmiş araçlar kılavuzu (2024)
ysoserial-plus.jar
– > 130 gadget zinciri içeren topluluk çatallaması:
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
marshalsec
– JNDI gadget üretimi için hala referans.gadget-probe
– ağ hizmetlerine karşı hızlı siyah kutu gadget keşfi.SerialSniffer
–ObjectInputStream
tarafından okunan her sınıfı yazdıran JVMTI ajanı (filtreler oluşturmak için yararlıdır).- Tespit ipucu – filtre kararlarını ve reddedilen sınıfları günlüğe kaydetmek için
-Djdk.serialDebug=true
(JDK 22+) etkinleştirin.
Güvenli readObject()
uygulamaları için hızlı kontrol listesi
- Metodu
private
yapın ve@Serial
anotasyonunu ekleyin (statik analize yardımcı olur). - Kullanıcı tarafından sağlanan metodları asla çağırmayın veya metod içinde I/O gerçekleştirmeyin – yalnızca alanları okuyun.
- Doğrulama gerekiyorsa, deserialization'dan sonra,
readObject()
dışında gerçekleştirin. - Varsayılan serileştirme yerine
Externalizable
uygulamayı tercih edin ve açık alan okumaları yapın. - İç hizmetler için bile sertleştirilmiş bir
ObjectInputFilter
kaydedin (uzlaşma dayanıklı tasarım).
Referanslar
- Spring Security Advisory – CVE-2023-34040 Java Deserialization in Spring-Kafka (Ağu 2023)
- GitHub Security Lab – GHSL-2023-044: Unsafe Deserialization in Aerospike Java Client (Tem 2023)
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.