Zum Inhalt springen

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
Schwachstellenklassen Glossar

Insecure Deserialization - Unsichere Deserialisierung

Insecure Deserialization (OWASP A08:2021) tritt auf wenn eine Anwendung serialisierte Objekte aus nicht vertrauenswürdigen Quellen verarbeitet ohne ausreichende Validierung. Angreifer manipulieren serialisierte Daten um beim Deserialisieren beliebige Methoden aufzurufen (Gadget-Chains). Betroffen sind Java (readObject), PHP (unserialize), Python (native Serialisierungsformate), .NET (BinaryFormatter) und Ruby (Marshal.load). Resultat: Remote Code Execution, Privilege Escalation oder Denial of Service.

Insecure Deserialization ist eine der komplexesten Schwachstellenklassen - und gleichzeitig eine mit enormem Impact-Potential. Das Kernproblem: Serialisierung ist ein mächtiger Mechanismus der Objekte in ein Format umwandelt das übertragen oder gespeichert werden kann. Wenn die Deserialisierung diese Daten ohne Misstrauen verarbeitet, wird die gesamte Objektstruktur zum Angriffsvektor.

Grundprinzip

Serialisierung vs. Deserialisierung:

Serialisierung: Objekt → Bytes/Text (zur Übertragung/Speicherung)
Deserialisierung: Bytes/Text → Objekt (Rekonstruktion)

Problem bei unsicherer Deserialisierung:
  → Angreifer kontrolliert die serialisierten Bytes/Daten
  → Er kann ein präpariertes Objekt injizieren
  → Beim Deserialisieren werden "magische" Methoden aufgerufen
  → Diese Methoden führen bei normaler Programmlogik beliebigen Code aus!

Wo kommen serialisierte Daten vor?
  → HTTP-Cookies (Base64-kodierte serialisierte Session-Objekte!)
  → HTTP-Body in POST-Requests
  → Datenbankfelder (BLOB mit serialisierten Objekten)
  → Cache-Systeme (Redis, Memcached)
  → Message-Queues (RabbitMQ, Kafka mit Java-Objekten)
  → API-Parameter und Hidden-Form-Fields

Angriffstypen nach Sprache

1. PHP-Deserialisierung:

   PHP-Serialisierungsformat (erkennbar):
   O:4:"User":2:{s:4:"name";s:5:"Alice";s:4:"role";s:4:"user";}
   → Objekt (O) der Klasse "User" mit 2 Eigenschaften

   Magische PHP-Methoden die bei Deserialisierung aufgerufen werden:
   __wakeup()    → automatisch beim Deserialisieren aufgerufen
   __destruct()  → beim Objekt-Löschen nach Skriptende
   __toString()  → wenn Objekt als String verwendet wird

   Angriffs-Prinzip:
   → Klasse mit gefährlicher __wakeup()/__destruct()-Methode identifizieren
   → Eigenes serialisiertes Objekt dieser Klasse erstellen
   → Gefährlichen Wert setzen → bei Deserialisierung Codeausführung!

   Typische Einsatzorte für PHP unserialize():
   → Cookie-Wert, Hidden-Form-Field, API-Parameter
   → Erkennung im Code: grep -r "unserialize(" /var/www/

   Schutz:
   → unserialize() nie auf externe Daten (ohne HMAC-Signatur)
   → allowed_classes-Parameter nutzen (PHP 7.0+):
     unserialize($data, ["allowed_classes" => ["SafeClass"]])
   → JSON statt PHP-Serialisierung für externe Daten

2. Java-Deserialisierung:

   Java Serialization: ObjectInputStream.readObject()
   Erkennungsmerkmal in HTTP-Traffic:
   → "rO0AB" am Anfang (Base64) oder "\xAC\xED\x00\x05" (Bytes)

   Gadget-Chains:
   → Gadget = Klasse die bei Deserialisierung nützliche Aktionen für Angreifer ausführt
   → In populären Bibliotheken: Commons Collections, Spring, Groovy, Hibernate
   → Chain: Gadget A ruft B auf → B ruft C auf → C führt Code aus

   Pentest-Tool ysoserial:
   → Generiert präparierte Java-Serialisierungsobjekte für autorisierte Tests
   → Unterstützte Chains: CommonsCollections1-7, Spring1, Groovy1
   → Payload → bei Deserialisierung: Befehlsausführung auf Server

   Schutz Java:
   → ObjectInputFilter (Java 9+): erlaubte Klassen-Allowlist
   → Jackson/GSON/Protocol Buffers statt Java-native-Serialisierung
   → serialkiller-Filter: Blockliste bekannter Gadget-Klassen
   → Deserialisierung in Sandbox (isolierter Prozess)

3. Python native Serialisierungsformate:

   Native Python-Serialisierung erlaubt __reduce__-Methode:
   → Klasse kann bei Deserialisierung beliebige Funktion aufrufen
   → NIEMALS für externe/nicht-vertrauenswürdige Daten verwenden!

   Sichere Alternativen für Python:
   → json.dumps/json.loads: JSON ohne Code-Execution-Risiko
   → Pydantic, marshmallow: schema-basierte sichere Deserialisierung
   → Protocol Buffers, MessagePack: typ-sicher, kein Code-Execution

4. .NET BinaryFormatter (vollständig deprecated!):

   BinaryFormatter: von Microsoft in .NET 7+ vollständig entfernt
   → War unsicher by Design: keine Klassen-Filterung
   → Migration: System.Text.Json, MessagePack, Protobuf

5. Ruby Marshal:

   Marshal.load auf externe Daten: Ruby-Objekt-Gadget-Chains möglich
   Schutz: JSON, MessagePack für alle externen Daten verwenden

Erkennung im Pentest

Deserialisierung in HTTP-Traffic erkennen:

Erkennungsmerkmale:
  PHP serialized:   O:4:"User":0:{} oder a:2:{i:0;s:5:"hello";}
  Java serialized:  rO0ABVN... (Base64) oder %AC%ED%00%05 (URL-encoded)
  .NET:            AAEAAAD/////...
  Ruby Marshal:    BAh... (Base64)

Burp Suite Vorgehen:
  1. HTTP-Traffic mit Burp analysieren: Cookies, Body-Parameter, Header
  2. Base64-Wert mit "rO0AB" Prefix → Java-Deserialisierung!
  3. Burp Extension "Java Deserialization Scanner" installieren
  4. Präpariertes Payload aus ysoserial → in Burp Repeater einfügen
  5. Out-of-Band Nachweis: Burp Collaborator (DNS-Callback)

Automatisiertes Scanning:
  Nuclei: Templates für bekannte Deserialisierungs-Schwachstellen
  Burp Pro Active Scan: erkennt Java-Deserialisierung automatisch

Schutzmaßnahmen

Sichere Design-Entscheidungen:

Empfohlene Formate (KEINE Code-Execution möglich):
  JSON:              Einfachste und sicherste Option
  MessagePack:       Binär + kompakt + typ-sicher
  Protocol Buffers:  Schema-definiert, Google Standard
  CBOR:              Compact Binary Object Representation
  Apache Avro:       Schema-versioniert, für Big Data

Wenn Deserialisierung unvermeidbar:
  1. HMAC-Signatur über serialisierte Daten:
     → Nur HMAC-signierte Daten deserialisieren
     → Schlüssel auf Server-Seite (Angreifer kann nicht gültig signieren)
     → Signatur vor Deserialisierung prüfen - Fehlschlag → reject

  2. Klassen-Allowlist:
     Java:   ObjectInputFilter → nur erlaubte Klassen deserialisieren
     PHP:    allowed_classes-Parameter für unserialize()
     .NET:   System.Text.Json mit bekannten Types

  3. Sandbox-Isolation:
     → Deserialisierung in isoliertem Prozess (eigene JVM/Python-Env)
     → Kein Netzwerkzugriff, kein Filesystem-Zugriff im Sandbox-Prozess
     → Bei Exception: Process killen → kein Schaden

  4. Monitoring:
     → Deserialisierungs-Exceptions loggen + SIEM-Alert
     → Unbekannte Klassen-Namen in Payloads: Alert!

Entwickler-Checkliste:
  □ Externe Daten niemals direkt deserialisieren (ohne Signatur + Allowlist)
  □ Native Serialisierung für externe Daten? → sofort auf JSON/Protobuf migrieren
  □ Session-Daten: serverseitig in DB speichern (kein Session-Objekt im Cookie)
  □ Wenn Cookie-basierte Session: JWT mit RS256 (stateless, keine Deserialisierung)
  □ Bibliotheken auf aktuellem Stand halten: Gadget-Chains nur in alten Versionen!
  □ SAST-Scan: Semgrep findet unsichere Deserialisierungs-Aufrufe in Code

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung