Seriøs sikkerhet: GnuTLS følger OpenSSL, fikser tidsangrepsfeil

Seriøs sikkerhet: GnuTLS følger OpenSSL, fikser tidsangrepsfeil

Kilde node: 1956368

Forrige uke skrev vi om en haug med minnehåndteringsfeil som ble fikset i den siste sikkerhetsoppdateringen til det populære OpenSSL-krypteringsbiblioteket.

Sammen med disse minnefeilene rapporterte vi også om en feil kalt CVE-2022-4304: Timing Oracle i RSA-dekryptering.

I denne feilen, skyte den samme krypterte meldingen om og om igjen på en server, men modifisere utfyllingen på slutten av dataene for å gjøre dataene ugyldige, og dermed provosere en slags uforutsigbar oppførsel...

... ville ikke ta en konsistent tid, forutsatt at du var nær målet på nettverket, at du pålitelig kunne gjette hvor lang tid dataoverføringsdelen av prosessen ville ta.

Ikke alle data behandles likt

Hvis du avfyrer en forespørsel, bestemmer hvor lang tid svaret tar, og trekker fra tiden som er brukt i sending og mottak av nettverksdata på lavt nivå, vet du hvor lang tid serveren brukte på å gjøre sin interne beregning for å behandle forespørselen .

Selv om du ikke er sikker på hvor mye tid som er brukt opp i nettverket, kan du se etter variasjoner i tur-retur-tider ved å skyte av mange forespørsler og samle massevis av prøver.

Hvis nettverket er pålitelig nok til å anta at nettverksoverheaden stort sett er konstant, kan du kanskje bruke statistiske metoder for å utlede hvilken type datamodifikasjon som forårsaker hva slags ekstra behandlingsforsinkelse.

Fra dette kan du mange utlede noe om strukturen, eller til og med innholdet, til de originale ukrypterte dataene som skal holdes hemmelig i hver gjentatt forespørsel.

Selv om du bare kan trekke ut én byte med ren tekst, vel, det er ikke ment å skje.

Såkalte timing av angrep av denne typen er alltid plagsomme, selv om du kanskje må sende millioner av falske pakker og time dem alle for å ha noen sjanse til å gjenopprette bare én byte med klartekstdata...

…fordi nettverk er raskere, mer forutsigbare og i stand til å håndtere mye mer belastning enn de var for bare noen få år siden.

Du tror kanskje at millioner av forræderske pakker spammet til deg i løpet av for eksempel den neste timen ville skille seg ut som en slags tommel.

Men "en million pakker i timen mer eller mindre enn vanlig" er rett og slett ikke en spesielt stor variasjon lenger.

Lignende "oracle"-feil i GnuTLS

Vel, den samme personen som rapporterte feilen med fast-til-siste-tidspunkt i OpenSSL, rapporterte også en lignende feil i GnuTLS omtrent samtidig.

Denne har feilidentifikatoren CVE-2023-0361.

Selv om GnuTLS ikke er fullt så populær eller mye brukt som OpenSSL, har du sannsynligvis en rekke programmer i IT-området ditt, eller til og med på din egen datamaskin, som bruker det eller inkluderer det, muligens inkludert FFmpeg, GnuPG, Mplayer, QEMU , Rdesktop, Samba, Wget og Wireshark.

Ironisk nok dukket tidsfeilen i GnuTLS opp i kode som i utgangspunktet skulle logge tidsangrepsfeil.

Som du kan se av kodeforskjellen (diff) nedenfor, var programmereren klar over at enhver betinget (if ... then) operasjon som brukes til å sjekke og håndtere en dekrypteringsfeil kan gi tidsvariasjoner, fordi CPU-er vanligvis tar forskjellig tid avhengig av hvilken vei koden din går etter en "gren"-instruksjon.

(Dette gjelder spesielt for en gren som ofte går den ene veien og sjelden den andre, fordi prosessorer har en tendens til å huske, eller cache, kode som kjører gjentatte ganger for å forbedre ytelsen, og dermed gjøre at koden som sjelden tas, kjører detekterbart tregere.)

Kodeforskjell for gnutls-3.7.8/lib/auth/rsa.c mot 3.7.9

Men programmereren ønsket fortsatt å logge at et angrep kan skje, noe som skjer hvis if (ok) testen ovenfor mislykkes og forgrener seg til else { ... } seksjon.

På dette tidspunktet kaller koden _gnutls_debug_log() funksjon, som kan ta lang tid å gjøre jobben sin.

Derfor satte koderen inn et bevisst anrop til _gnutls_no_log() i then { ... } del av koden, som later til å logge et "angrep" når det ikke er et, for å prøve å jevne opp tiden koden bruker i begge retninger som if (ok) gren instruksjon kan ta.

Tilsynelatende var imidlertid de to kodebanene ikke tilstrekkelig like i tiden de brukte opp (eller kanskje _gnutls_debug_log() funksjonen alene var utilstrekkelig konsistent i håndteringen av forskjellige typer feil), og en angriper kunne begynne å skille dekrypteringssignaler etter en million forsøk.

Hva gjør jeg?

Hvis du er en programmerer: feilrettingen her var enkel, og fulgte "less is more"-prinsippet.

Koden i rosa ovenfor, som ble ansett for å ikke gi veldig nyttige angrepsdeteksjonsdata uansett, ble ganske enkelt slettet, med den begrunnelse at kode som ikke er der ikke kan kompileres inn ved en feiltakelse, uavhengig av byggeinnstillingene dine...

...og kode som ikke er kompilert i kan aldri kjøres, verken ved et uhell eller design.

Hvis du er en GnuTLS-bruker: den nylig utgitte versjonen 3.7.9 og den "nye produktsmaken" 3.8.0 har denne løsningen, sammen med diverse andre, inkludert.

Hvis du kjører en Linux-distro, se etter oppdateringer til alle sentralstyrte delte bibliotekversjoner av GnuTLS du har, samt apper som tar med sin egen versjon.

På Linux, søk etter filer med navnet libgnutls*.so for å finne eventuelle delte biblioteker som ligger rundt, og søke etter gnutls-cli for å finne eventuelle kopier av kommandolinjeverktøyet som ofte følger med biblioteket.

Du kan kjøre gnutls-cli -vv for å finne ut hvilken versjon av libgnutls den er dynamisk knyttet til:

 $ gnutls-cli -vv gnutls-cli 3.7.9 <-- min Linux-distro fikk oppdateringen sist fredag ​​(2023-02-10)

Tidstempel:

Mer fra Naken sikkerhet