Serialisieren heißt, strukturierte Daten (ein Array, ein Objekt) in Text zu verwandeln, um sie zu speichern oder zu übertragen; Deserialisieren ist der umgekehrte Vorgang. Problematisch wird es, wenn die wiederherzustellenden Daten von außen kommen: aus einem Cookie, einem Formularfeld, einem URL-Parameter. MITRE führt diese Schwachstelle als CWE-502, „Deserialization of Untrusted Data“; in PHP spricht man auch von PHP Object Injection.
So funktioniert der Angriff in PHP
Ein serialisierter PHP-String beschreibt den Typ dessen, was er enthält. So steht O:4:"User":1:{s:4:"name";s:3:"Bob";} für ein Objekt der Klasse User mit einer Eigenschaft name. Ein Angreifer, der diesen String kontrolliert, kann unserialize() also anweisen, ein Objekt einer beliebigen Klasse zu erzeugen, die auf der Website geladen ist, mit den Werten seiner Wahl.
Gefährlich wird dieses Objekt durch die magischen Methoden, die PHP automatisch aufruft: __wakeup() beim Wiederherstellen, __destruct() beim Zerstören, __toString(), wenn das Objekt als Text verwendet wird. Indem der Angreifer Klassen verkettet, die schon im Code der Website stecken und deren Methoden sich gegenseitig aufrufen, baut er eine Gadget-Kette (POP Chain), die in einer gefährlichen Aktion endet: Löschen einer Datei, Schreiben einer PHP-Datei, Ausführung von Code aus der Ferne.

Ein Beispiel aus WordPress: GiveWP
Die Schwachstelle CVE-2024-5932 im Spenden-Plugin GiveWP, bis einschließlich Version 3.14.1, erlaubte einem nicht angemeldeten Angreifer, über den Parameter give_title ein PHP-Objekt einzuschleusen. Eine im Plugin vorhandene Gadget-Kette führte zur Ausführung von Code und zum Löschen von Dateien; der veröffentlichte CVSS-3.1-Score liegt bei 10. Unser Beitrag zur PHP Object Injection beschreibt diesen Fall und den Mechanismus im Detail.
Deserialisierung ist für Angreifer auch dann nützlich, wenn sie schon drin sind: Die Hintertür, die 2025 in das Plugin-Portfolio von EssentialPlugin eingebaut wurde, stützte sich auf unserialize, wie unser Beitrag zu Supply-Chain-Angriffen zeigt.
In WordPress: unserialize und maybe_unserialize
WordPress speichert viele serialisierte Daten, vor allem in der Optionstabelle und in den Metadaten. Zum Zurücklesen dient die Funktion maybe_unserialize(): Sehen die Daten serialisiert aus (is_serialized()), ruft sie unserialize() auf, ohne die erlaubten Klassen einzuschränken. Sie bietet also keinerlei Schutz und darf nie Daten bekommen, die von einem Besucher stammen.
- Daten als JSON austauschen: Die PHP-Dokumentation empfiehlt
json_encode()undjson_decode()für alle Daten, die über den Benutzer laufen. JSON erzeugt nie Objekte beliebiger Klassen. - Nicht zu viel von
allowed_classeserwarten: Diese Option vonunserialize()schränkt ein, welche Klassen instanziiert werden, aber das PHP-Handbuch stellt klar, dass nicht vertrauenswürdige Daten unabhängig von ihrem Wert nicht an diese Funktion übergeben werden sollten. - Signieren, was hin und her geht: Wenn serialisierte Daten wirklich über den Browser laufen müssen, verhindert eine HMAC-Signatur, die vor jedem Lesen geprüft wird, dass sie manipuliert werden.
- PHP aktuell halten: Seit PHP 8.0 werden die Metadaten von Phar-Archiven nicht mehr automatisch deserialisiert, was einen Angriffsweg über Dateieinbindung und Wrapper geschlossen hat.
Für Administratoren bleibt das Update der betroffenen Plugins die wichtigste Abwehr, denn die Lücke steckt in deren Code. Eine Web Application Firewall kann verdächtige serialisierte Strings in der Zwischenzeit blockieren, und die Schwachstellenwarnungen von WP Masquerade Pro sagen dir, wenn ein installiertes Plugin zu den betroffenen Versionen gehört. WP Masquerade selbst filtert keine Anfragen.