Deserialisatie: de achilleshiel van programmeertalen

deserialisatie

Deserialisatiebugs vormen één van de meeste onderschatte kwetsbaarheden in mainstream programmeertalen. Een diepere analyse van de risico’s van deserialisatie.

‘Serialisatie’ en ‘deserialisatie’ zijn normaal geen termen die een onmiddellijke paniekaanval veroorzaken bij  softwareprogrammeurs. Het zijn veelgebruikte technieken om objecten te verzenden naar bibliotheken. Dit proces is echter niet vrij van risico’s.

Net zoals andere IT-technieken kan ook deserialisatie misbruikt worden voor slechte doeleinden. In het recente verleden hebben zogenaamde deserialisatiebugs al meermaals aan de oorzaak gelegen van grootschalige cyberaanvallen. OWASP (Open Web Application Security Project) beschouwt deserialisatie als één van de top tien meest ernstige bedreigingen voor webapplicaties.

Van serialisatie tot deserialisatie

Eerst dienen we goed te begrijpen wat er nu precies gebeurt tijdens het serialisatie- en deserialisatieproces. Eenvoudig gezegd is serialiseren het verzendklaar maken van een object. Net zoals bij communicatie tussen mensen is het bij communicatie tussen servers van belang dat verzender en ontvanger dezelfde taal spreken.

Tijdens de serialisatie zet je het object om naar een universeler gegevensformaat dat de meeste servers kunnen verwerken. Veelgebruikte standaarden hiervoor zijn xML (eXtensible Markup Language) en JSON (JavaScript Object Notation).

Deserialiseren is dan vervolgens het uitpakken van die bestanden en ze weer omzetten naar de ‘moedertaal’ van de bibliotheek. Deserialisatie kan worden toegepast in de meeste mainstream programmeertalen zoals Java, PHP en .NET. Tot zover dus niets om je zorgen over te maken.

Remote Code Execution

Dat komt misschien wel als je weet dat er tot heden al meer dan 300 kwetsbaarheden (CVE’s) in de mainstream programmeertalen gekend zijn die kunnen gelinkt worden aan deserialisatie. Daar moet je dan nog een hoop kwetsbaarheden bij denken die onderzoekers nog niet hebben opgespoord.

Deserialisatie kan een systeem kwetsbaar maken voor remote code execution. Hierbij voert een aanvaller vanop afstand code uit om de controle over een systeem helemaal over te nemen. Aanvallers kunnen een bytestream in gang zetten die, eens hun bronbestand gedeserialiseerd wordt op het gastapparaat, een ketting maakt van stukjes code.

Zo krijgen ze langzaam maar zeker de controle over de hele bibliotheek. Daar kunnen aanvallers schadelijke stukken code in de broncode van software en applicaties aanbrengen. Eens je als ontvanger het object volledig hebt gedeserialiseerd, is er geen weg meer terug.  

Log4Shell

Dat deserialisatiekwetsbaarheden niet te licht mogen worden genomen, bewijzen enkele grootschalige incidenten uit het recente verleden. In 2016 stuurden cybercriminelen de servers van de openbare vervoermaatschappij van de Amerikaanse stad San Francisco in de war met een deserialisatie-aanval. Het zorgde ervoor dat het netwerk van de maatschappij geen betalingen meer kon verwerken en iedereen plots gratis met het openbaar vervoer kon rijden.

Ook het fameuze Log4Shell-incident was het gevolg van een deserialisatiebug in de populaire Java-logbibliotheek Apache Log4j. De kwetsbaarheid maakte het mogelijk om vanop afstand code uit te voeren in de backoffice van een webapplicatie. Toen de bug eind 2021 aan de oppervlakte kwam, gingen terecht alle alarmbellen af.

Duizenden websites maakten immers gebruik van Log4j, waaronder ook grote namen zoals Amazon en Twitter. De kwetsbaarheid kon in potentie dus duizenden organisaties en miljarden internetgebruikers treffen. Meerdere patches bleken uiteindelijk nodig om het lek helemaal te dichten.

log4j deserialisatie
Deserialisatie lag aan de hoofdoorzaak van Log4Shell.

Deserialisatie in Java

Mede door de grootschaligheid van Log4Shell is deserialisatie ook meer onder de aandacht van de academische wereld gekomen. Een recente studie door de universiteiten van Toulouse (Frankrijk), Umeå (Zweden), Paderborn (Duitsland) en Luxemburg brengt deserialisatierisico’s in Java voor het eerst gedetailleerd in kaart.

De onderzoekers kwamen onder meer tot de conclusie dat deserialisatiebugs het meest frequent voorkomen in Java. Van de 364 tot heden geregistreerde kwetsbaarheden zijn een honderdtal alleen al ontdekt in Java-bibliotheken. Sinds 2016 is het aantal kwetsbaarheden ook significant toegenomen. Een zorgwekkende statistiek, gezien miljoenen applicaties geschreven zijn in Java.

Veel kwetsbaarheden blijken eenzelfde hoofdoorzaak te delen: het deserialiseren van objecten die afkomstig zijn van een niet-geverifieerde bron. De veiligheidsrichtlijnen voor Java SE omschrijven dit nochtans als een hoofdzonde. Toch blijken programmeurs in de praktijk ofwel onvoldoende op de hoogte te zijn van de richtlijnen of niet over de juiste middelen te beschikken om een bron te verifiëren.

Vicieuze cirkel

Een andere zorgwekkende vaststelling die de onderzoekers maakten is dat deserialisatiekwetsbaarheden zelden snel van een patch voorzien worden. De populariteit van een bibliotheek heeft ook maar beperkt impact op de snelheid van patches. Bij talloze kwetsbaarheden heeft het jaren geduurd vooraleer ze konden worden opgelost. Een kwetsbaarheid in de veelgebruikte bibliotheek Apache Commons Collection bleef ooit eens elf jaar lang ongepatcht.

De moeilijkheden om deserialisatiebugs op te lossen starten volgens de onderzoekers vaak al bij de ontdekking ervan. In de omschrijvingen van CVE’s worden systematisch te vage of zelfs foutieve definities voor deserialisatie gehanteerd.

Dat zet een vicieuze cirkel in gang waarbij ernstige kwetsbaarheden lang onder de radar kunnen blijven omdat er onvoldoende kennis over bestaat. Er is dus nood aan een efficiënter mechanisme om deserialisatiebugs sneller op te sporen en onschadelijk te maken.

java
Deserialisatiebugs komen het vaakst voor in Java.

De ketting breken

Krijg je te maken met een deserialisatie-aanval, dan blijkt het verwijderen van de serialisatie-interface de meest effectieve verdediging. Deze handeling breekt de bytestroom die de aanvallers in gang proberen te zetten af. Ook het wijzigen van de bibliotheekversie of het blokkeren van de toegang tot sommige poorten voor het object verkleint de kans op actieve uitbuiting van een kwetsbaarheid.

Het is ook aangeraden om preventief gebruik te maken van de readObject-methode. Hiermee kan je een geserialiseerd object lezen vanuit de bytestream. Dit kan aan het licht brengen dat er geknoeid is met de gegevensstroom alvorens je het object uitpakt of het deserialisatieproces afbreken als er onregelmatigheden zouden optreden.

Deserialisatie speelt zich af in het hart van applicaties. Zonder een gezond hart kan geen enkel organisme lang overleven. Het is dan ook van vitaal belang dat de mogelijke risico’s van deserialisatie niet meer verborgen blijven.

nieuwsbrief

Abonneer je gratis op ITdaily !

  • This field is for validation purposes and should be left unchanged.