Allvarlig säkerhet: GnuTLS följer OpenSSL, fixar timing attack bugg

Allvarlig säkerhet: GnuTLS följer OpenSSL, fixar timing attack bugg

Källnod: 1956368

Förra veckan skrev vi om ett gäng minneshanteringsbuggar som fixades i den senaste säkerhetsuppdateringen av det populära OpenSSL-krypteringsbiblioteket.

Tillsammans med dessa minnesbuggar rapporterade vi också om en bugg dubbad CVE-2022-4304: Timing Oracle i RSA-dekryptering.

I det här felet, avfyrar samma krypterade meddelande om och om igen på en server, men modifierar utfyllnaden i slutet av data för att göra data ogiltiga, och på så sätt provocera fram något slags oförutsägbart beteende...

… skulle inte ta en konsekvent tid, förutsatt att du var nära målet på nätverket att du tillförlitligt kunde gissa hur lång tid dataöverföringen av processen skulle ta.

Alla uppgifter behandlas inte lika

Om du avfyrar en förfrågan, tar tid på hur lång tid svaret tar och subtraherar den tid som åtgår vid sändning och mottagning av nätverksdata på låg nivå, vet du hur lång tid det tog för servern att göra sin interna beräkning för att bearbeta förfrågan .

Även om du inte är säker på hur mycket tid som går åt i nätverket, kan du leta efter variationer i tur och retur-tider genom att avfyra massor av förfrågningar och samla in massor av prover.

Om nätverket är tillräckligt tillförlitligt för att anta att nätverkskostnaderna i stort sett är konstanta, kanske du kan använda statistiska metoder för att sluta sig till vilken typ av datamodifiering som orsakar vilken typ av extra bearbetningsfördröjning.

Av detta kan du många dra slutsatser om strukturen, eller till och med innehållet, av den ursprungliga okrypterade datan som ska hållas hemlig i varje upprepad begäran.

Även om du bara kan extrahera en byte klartext, ja, det är inte meningen att det ska hända.

Så kallade tajma attacker av det här slaget är alltid besvärliga, även om du kan behöva skicka miljontals falska paket och tajma dem alla för att ha någon chans att återställa bara en byte med klartextdata...

…eftersom nätverk är snabbare, mer förutsägbara och kan hantera mycket mer belastning än de var för bara några år sedan.

Du kanske tror att miljontals förrädiska paket som spammades till dig under, till exempel, nästa timme skulle sticka ut som en sorts tumme.

Men "en miljon paket i timmen mer eller mindre än vanligt" är helt enkelt inte en särskilt stor variation längre.

Liknande "oracle"-bugg i GnuTLS

Tja, samma person som rapporterade buggtiden för fixad-at-sist bugg i OpenSSL rapporterade också en liknande bugg i GnuTLS ungefär samtidigt.

Den här har buggidentifieraren CVE-2023-0361.

Även om GnuTLS inte är riktigt lika populärt eller allmänt använt som OpenSSL, har du förmodligen ett antal program i din IT-anläggning, eller till och med på din egen dator, som använder det eller inkluderar det, möjligen inklusive FFmpeg, GnuPG, Mplayer, QEMU , Rdesktop, Samba, Wget och Wireshark.

Ironiskt nog dök timingfelet i GnuTLS upp i kod som var tänkt att logga timingattackfel i första hand.

Som du kan se av kodskillnaden (diff) nedan var programmeraren medveten om att alla villkorade (if ... then) operation som används för att kontrollera och hantera ett dekrypteringsfel kan ge tidsvariationer, eftersom CPU:er i allmänhet tar olika lång tid beroende på vilken väg din kod går efter en "branch"-instruktion.

(Detta gäller särskilt för en gren som ofta går åt det ena hållet och sällan åt det andra, eftersom CPU:er tenderar att komma ihåg, eller cachelagra, kod som körs upprepade gånger för att förbättra prestandan, vilket gör att den sällan tagna koden går detekterbart långsammare.)

Koddiff för gnutls-3.7.8/lib/auth/rsa.c mot 3.7.9

Men programmeraren ville fortfarande logga att en attack kan hända, vilket händer om if (ok) testet ovan misslyckas och grenar in i else { ... } sektion.

Vid denna tidpunkt anropar koden _gnutls_debug_log() funktion, som kan ta ganska lång tid att utföra sitt arbete.

Därför infogade kodaren ett avsiktligt samtal till _gnutls_no_log() i then { ... } en del av koden, som låtsas logga en "attack" när det inte finns en, för att försöka jämna ut tiden som koden spenderar i endera riktningen som if (ok) greninstruktion kan ta.

Tydligen var dock de två kodvägarna inte tillräckligt lika under den tid de använde (eller kanske _gnutls_debug_log() funktion på egen hand var otillräckligt konsekvent för att hantera olika typer av fel), och en angripare kunde börja urskilja dekrypteringsbesked efter en miljon försök eller så.

Vad göra?

Om du är en programmerare: buggfixen här var enkel och följde principen "less is more".

Koden i rosa ovan, som ansågs inte ge särskilt användbar attackdetekteringsdata ändå, raderades helt enkelt, med motiveringen att kod som inte finns där inte kan kompileras in av misstag, oavsett dina bygginställningar...

...och kod som inte är kompilerad i kan aldrig köras, vare sig av misstag eller design.

Om du är en GnuTLS-användare: den nyligen släppta versionen 3.7.9 och den "nya produktsmaken" 3.8.0 har denna fix, tillsammans med olika andra, inkluderade.

Om du kör en Linux-distro, leta efter uppdateringar till alla centralt hanterade delade biblioteksversioner av GnuTLS du har, såväl som för appar som tar med sin egen version.

På Linux, sök efter filer med namnet libgnutls*.so för att hitta eventuella delade bibliotek som ligger och söka efter gnutls-cli för att hitta några kopior av kommandoradsverktyget som ofta ingår i biblioteket.

Du kan springa gnutls-cli -vv för att ta reda på vilken version av libgnutls den är dynamiskt länkad till:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <-- min Linux-distro fick uppdateringen i fredags (2023-02-10)

Tidsstämpel:

Mer från Naken säkerhet