Wat een interessante exploit! Ik heb net even snel door de paper heen gescanned, en ze hebben wel een leuke en interessante manier gevonden om SEV te omzeilen. Laat ik het eens proberen wat versimpeld uit te leggen (uitgaande van Type-1 virtualisatie), maar eerst wat achtergrond over virtualisatie en adres vertaling:
Intro virtualisatie/adres vertaling
Ten eerste; dit gaat over (server) systemen die met een virtualisatie laag draaien; met andere woorden, een of meerdere besturingssystemen draaien elk in hun eigen virtuele machine op dezelfde fysieke machine, net alsof ze onafhankelijke computers zijn. Deze techniek wordt bijna overal in datacenters en in de cloud toegepast omdat je veel oude services kan consolideren op grote multi-core machines, en je veel flexibeler en efficienter bent in het gebruiken van je hardware. Om deze virtuele machines te beheren draait er een
Hypervisor die de fysieke machine opsplitst en deelt tussen de virtuele machines die hun eigen besturingssysteem draaien.
Op een computer zonder virtualisatie laag doet het besturingssysteem ook aan een vorm van virtualisatie; elk programma, oftwel proces, dat draait heeft zijn eigen stuk geheugen toegewezen en zijn eigen geheugen adressen. Een besturingssysteem doet dit door virtuele adressen aan te maken en de processor te programmeren zodat deze automatisch vertaald worden naar de fysieke locaties in het geheugen. Deze Virtual Addess (VA) to Physical Address (PA) vertaling wordt gedaan door de
Memory Management Unit in je processor, oftewel MMU. Het besturingssysteem heeft voor elk proces een tabel (de page table - al is het op de meeste processoren een boom-structuur) die de vertaling van adressen bepaald, en de
Translation Lookaside Buffer (TLB) is een cache die de meest recente vertalingen bijhoudt zodat ze niet steeds opnieuw opgezocht hoeven worden. Doordat elk proces zijn eigen VA's heeft kan je niet zomaar bij het geheugen van een ander proces.
Wil je nu het bovenstaande model virtualiseren en meerdere onafhankelijke machines op een enkele server kunnen draaien, dan zal je moeten voorkomen dat de gebruikte PA's van de onderliggende besturingssystemen niet overlappen, en je zal ook je fysieke geheugen moeten partitioneren. Dit is een van de taken van de Hypervisor (HV), en dat doet deze door een 2e laag adres vertaling te introduceren. Deze translatie zal de door een guest besturingssysteem geziene PA's vertalen naar werkelijk fysieke geheugen locaties. Vandaar dat je in het diagram bij dit artikel de GVA en GPA regios ziet; de Guest Virtual Addresses - de virtuele adressen gezien door een proces wat binnen een virtuele machine draait, en de Guest Physical Address - de adressen die het besturingssysteem binnen de virtuele machine beschouwt als zijn fysieke adressen, maar die door de HV laag nog (onzichtbaar voor het besturingssysteem) normaals vertaald worden.
Wat is SEV?
In Secure Encrypted Virtualization kan een guest besturingssysteem zijn Guest Physical Address space versleutelen. Dit heeft enkele voordelen; mocht een andere guest in een virtuele machine toegang verkrijgen tot data via Hypervisor, dan kan deze niet zomaar het geheugen uitlezen van elke willekeurige ander virtuele machine omdat hij daar niet de juiste encryptie sleutel voor heeft. Het idee was ook dat een kwaadwillende Hypervisor zelf niet zomaar de data kan lezen van een virtuele machine, wat vooral in Cloud omgevingen interessant is waar je je virtuele machine draait op hardware van iemand anders, die je hoopt te kunnen vertrouwen.
Maar hoe werkt die exploit nou?
De exploit bestaat uit twee delen, en vereist dat de Hypervisor of kwaadwillend is, of op zijn minst door een andere exploit arbitraire code kan uitvoeren. Het gaat uit van een situatie waar er een bepaalde dienst in een virtuele machine draait die door de aanvaller zonder probleem benaderd kan worden, bijvoorbeeld een webserver.
Het eerste wat de aanvaller doet is een bepaald soort request naar de virtuele machine sturen, in het webserver geval bijvoorbeeld het downloaden van een bepaalde pagina of van een specifiek bestand. Dit bestand zal dan door de webserver uit het geheugen geladen worden en terug gestuurd (veel bestanden zullen in het geheugen gecached worden). De kwaadwillende Hypervisor moet dan de 2e niveau adres vertaling voor deze virtuele machine tijdelijk ongeldig maken, en zal dan verzoeken ontvangen om de vertaling te genereren wanneer de virtuele machine dit GPA probeert te benaderen. Door dit veelvuldig te doen kan de kwaadaardige HV er achter komen welke GPA adres regios overeen komen met de locatie van het bestand wat wordt opgevraagd in de requests naar de webserver.
Nu komt stap twee; aangezien de HV controle heeft over alle geheugen locaties die een guest heeft in zijn GPA regio, verandert de HV nu een van de adres mappings naar het bestand naar een arbitrair ander fysiek adres wat overeen komt met een ander geldig adres in de GPA regio. Dit is compleet onzichtbaar voor het besturingssysteem in de virtuele machine; in feite maakt de HV het geheugen nu corrupt, maar wanneer je wederom een request stuurt naar de webserver zal deze in plaats van de correcte inhoud van het bestand nu een ander deel van het fysieke geheugen van die virtuele machine verzenden, zelfs een deel waar het webserver proces normaal helemaal niet bij zou moeten kunnen. Aangezien het geheugen nog steeds wordt gelezen door de virtuele machine zelf, zal dit gewoon leesbaar zijn omdat het de juiste encryptie sleutels geinstalleerd heeft.
Maakt dat SEV dan waardeloos?
Nee, zeker niet, maar het biedt duidelijk geen bescherming tegen dit soort kwaadaardige Hypervisors. Deze exploit vereist dat er op Hypervisor niveau arbitraire code uitgevoerd moet kunnen worden, of dat er een malafide HV geinstalleerd wordt.
Ten eerste geeft SEV nog steeds wel bescherming tegen het lekken van data uit een virtuele machine naar een ander virtuele machine, mocht er een datalek via de Hypervisor zijn; zoals bijvoorbeeld de recente Spectre en Meltdown exploits. Dan zal je nog steeds versleutelde data lezen, en daar heb je als het goed is weinig aan. Ten tweede, op precies dezelfde manier ben je ook beschermd tegen de recente
Rowhammer aanvallen; omdat je niet meer weet wat/hoe de fysieke bits opgeslagen worden in je geheugen, ze zijn immers versleuteld, kan je niet zomaar een bit-flip forceren met het gewenste resultaat. Nou zal een EPYC server systeem ook vaak ECC geheugen gebruiken, wat voor zover ik weet op dit moment ook nog steeds niet vatbaar is voor Rowhammer aanvallen (behalve corruptie/denial of service dan).