Webbeveiliging

Onveilige deserialisatie

Definitie

Onveilige deserialisatie is een kwetsbaarheid die ontstaat wanneer een applicatie objecten opnieuw opbouwt uit gegevens die een aanvaller in handen heeft, bijvoorbeeld met unserialize() in PHP. De methoden die tijdens die reconstructie automatisch worden aangeroepen, kunnen leiden tot het verwijderen van bestanden of het uitvoeren van code.

Onveilige deserialisatie, Webbeveiliging

Serialiseren betekent gestructureerde gegevens (een array, een object) omzetten in tekst om ze op te slaan of te versturen; deserialiseren is de omgekeerde bewerking. Het probleem ontstaat wanneer de gegevens die weer worden opgebouwd van buitenaf komen: een cookie, een formulierveld, een URL-parameter. MITRE deelt deze zwakte in onder CWE-502, "deserialisatie van onbetrouwbare gegevens"; in PHP spreekt men ook van PHP object injection.

Hoe de aanval werkt in PHP

Een geserialiseerde PHP-string beschrijft zelf het type van wat erin zit. Zo staat O:4:"User":1:{s:4:"name";s:3:"Bob";} voor een object van de klasse User met een eigenschap name. Een aanvaller die deze string in handen heeft, kan unserialize() dus een object laten maken van elke klasse die de site heeft geladen, met de waarden die hij wil.

Dat object wordt gevaarlijk door de magische methoden die PHP automatisch aanroept: __wakeup() bij het opbouwen, __destruct() bij het opruimen, __toString() wanneer het object als tekst wordt gebruikt. Door klassen te combineren die al in de code van de site staan en elkaars methoden aanroepen, bouwt de aanvaller een gadget chain (POP-chain) die eindigt in een gevaarlijke actie: een bestand verwijderen, een PHP-bestand schrijven, remote code execution.

Verloop van een PHP object injection in vijf stappen: de aanvaller stuurt een vervalste geserialiseerde string in een cookie of veld, de applicatie roept unserialize() aan en bouwt een object van de gekozen klasse op, PHP voert automatisch de magische methoden __wakeup, __destruct of __toString uit, bestaande klassen roepen elkaar aan in een POP-gadget chain, en het eindresultaat is het verwijderen van bestanden, het schrijven van een PHP-bestand of het uitvoeren van code
Er wordt geen code rechtstreeks geïnjecteerd: de aanvaller misbruikt klassen die al in de site aanwezig zijn.

Een WordPress-voorbeeld: GiveWP

Het lek CVE-2024-5932 in de donatieplugin GiveWP, tot en met versie 3.14.1, liet een niet-geauthenticeerde aanvaller een PHP-object injecteren via de parameter give_title. Een gadget chain in de plugin leidde tot het uitvoeren van code en het verwijderen van bestanden; de gepubliceerde CVSS 3.1-score is 10. Ons artikel over PHP object injection gaat uitgebreid in op dit geval en het mechanisme.

Ook eenmaal binnen gebruiken aanvallers deserialisatie: de backdoor die in 2025 werd toegevoegd aan de pluginportfolio van EssentialPlugin draaide op unserialize, zoals ons artikel over supply-chain-aanvallen beschrijft.

Video: “Insecure Deserialization Attack Explained” (PwnFunction, in het Engels)

Voor WordPress: unserialize en maybe_unserialize

WordPress slaat veel geserialiseerde gegevens op, vooral in de optietabel en de metadata. De functie maybe_unserialize() leest ze terug: als de gegevens eruitzien als geserialiseerde data (is_serialized()), roept ze unserialize() aan, zonder de toegestane klassen te beperken. Ze biedt dus geen enkele bescherming en mag nooit gegevens van een bezoeker krijgen.

  • Wissel uit in JSON: de PHP-documentatie raadt json_encode() en json_decode() aan voor alle gegevens die via de gebruiker lopen. JSON maakt nooit objecten van willekeurige klassen aan.
  • Verwacht niet te veel van allowed_classes: deze optie van unserialize() beperkt welke klassen worden aangemaakt, maar de PHP-handleiding zegt dat je nooit onbetrouwbare gegevens aan deze functie moet doorgeven, ongeacht die waarde.
  • Onderteken wat heen en weer moet: als geserialiseerde gegevens echt via de browser moeten reizen, voorkomt een HMAC-handtekening die je vóór het lezen controleert dat iemand ze wijzigt.
  • Houd PHP up-to-date: sinds PHP 8.0 worden de metadata van phar-archieven niet meer automatisch gedeserialiseerd, wat een aanvalsroute rond bestandsinclusie en wrappers heeft gesloten.

Als beheerder is het belangrijkste verweer de betrokken plugins bij te werken, want het lek zit in hun code. Een web application firewall kan in de tussentijd verdachte geserialiseerde strings blokkeren, en de waarschuwingen voor kwetsbare plugins van WP Masquerade Pro laten je weten wanneer een geïnstalleerde plugin bij de getroffen versies hoort. WP Masquerade filtert zelf geen verzoeken.

Verder lezen

  • Artikel PHP-deserialisatie en objectinjectie uitgelegd
  • Pagina Meldingen over kwetsbare plugins

Bronnen

  1. MITRE CWE-502: Deserialization of Untrusted Data (externe link, opent in een nieuw tabblad)
  2. PHP Manual: unserialize() (externe link, opent in een nieuw tabblad)
  3. WordPress Developer Resources: maybe_unserialize() (externe link, opent in een nieuw tabblad)
  4. CVE Record: CVE-2024-5932 (externe link, opent in een nieuw tabblad)

Alle definities

WordPress-beveiliging, zonder ruis

Eén e-mail wanneer het ertoe doet: nieuw waargenomen aanvallen, updates van de plugin en praktische gidsen. Geen spam, afmelden met één klik.

Begin gratis, stap over op Pro wanneer je eraan toe bent

De gratis versie verbergt WordPress al en verplaatst de inlogpagina. Pro voegt aliassen, tweestapsverificatie en bewaking toe.