Spectre - ryhmä laitteiston haavoittuvuuksia , bugi useimmissa nykyaikaisissa prosessoreissa, jotka suorittavat spekulatiivisia käskyjäja edistynyt haaraennustus , joka mahdollistaa tietojen lukemisen kolmannen osapuolen kanavan kautta yhteisen välimuistihierarkian muodossa . Vaikuttaa useimpiin nykyaikaisiin mikroprosessoreihin, erityisesti x86/x86_64-arkkitehtuureihin (Intel ja AMD) ja joihinkin ARM -suoritinytimiin [1] .
Haavoittuvuus mahdollistaa sen, että paikalliset sovellukset (paikallinen hyökkääjä, kun ajetaan erikoisohjelmaa) pääsevät käsiksi nykyisen sovelluksen tai muiden ohjelmien virtuaalimuistin sisältöön [2] [3] [4] . Uhalle on määritetty kaksi CVE - tunnistetta: CVE-2017-5753 ja CVE-2017-5715 .
Spectterin löysivät itsenäisesti pohjoisamerikkalaisen Googlen ( Project Zero ) tutkijat ja Paul Kocherin kanssa yhteistyössä toiminut ryhmä, johon osallistuivat Grazin teknillisen yliopiston työntekijät . Haavoittuvuus löydettiin vuoden 2017 puolivälissä, ja siitä keskusteltiin ja korjattiin suljettuna useita kuukausia. Yksityiskohtien ja korjausten oli määrä julkaista 9. tammikuuta 2018, mutta haavoittuvuuden yksityiskohdat julkistettiin 4. tammikuuta 2018 samaan aikaan Meltdown -hyökkäyksen kanssa, johtuen The Register [5] -toimittajien julkaisuista, jotka saivat tietää KAISER/KPTI-korjaukset Meltdownin torjumiseksi Linux-ytimen postituslistalta [6] .
Spectre-vika mahdollistaa tietyllä tietokoneella käynnissä olevien haitallisten käyttäjäsovellusten lukuoikeuden mielivaltaisiin paikkoihin tietokoneen muistissa , jota uhriprosessi käyttää, kuten muihin sovelluksiin (eli katkaisee muistin eristyksen ohjelmien välillä). Spectre-hyökkäys vaikuttaa useimpiin tietokonejärjestelmiin, jotka käyttävät korkean suorituskyvyn mikroprosessoreita, mukaan lukien henkilökohtaiset tietokoneet, palvelimet, kannettavat tietokoneet ja monet mobiililaitteet [7] . Erityisesti Spectre-hyökkäys osoitettiin Intel- ja AMD -yritysten valmistamiin prosessoreihin sekä ARM -prosessoriytimiä käyttäviin siruihin .
Spectre-hyökkäyksestä on olemassa muunnos, joka käyttää JavaScript-ohjelmia päästäkseen käsiksi selaimien muistiin (lukee tietoja muista sivustoista tai selaimeen tallennettuja tietoja) [8] .
Oletetaan, että uhriprosessin koodinpätkä
if ( x < array1_size ) y = jono2 [ matriisi1 [ x ] * 256 ];on osa funktiota, joka vastaanottaa etumerkittömän kokonaisluvun x ei-luotettavasta lähteestä, ja tämän koodin suorittavalla prosessilla on pääsy etumerkittömien 8-bittisten kokonaislukujen taulukkoon , jonka koko on array1_size , ja toiseen etumerkitömien 8-bittisten kokonaislukujen matriisi2 . koko 64 kb.
Tämä katkelma alkaa tarkistamalla, että x on kelvollinen arvo. Ja tämä tarkistus on turvallisuuden kannalta välttämätön. Erityisesti se estää tietojen lukemisen taulukon1 rajojen ulkopuolella . Sen puuttuessa virheelliset x -arvot voivat joko heittää poikkeuksen, kun yritetään lukea tietoja prosessin käytettävissä olevan muistin ulkopuolelta, tai lukea prosessin käytettävissä olevia luottamuksellisia tietoja määrittämällä x = <salainen_tavun_osoite> - <array1_address_array1> .
Valitettavasti ehdollisen haaran virheellinen ennuste käskyjen spekulatiivisessa suorituksessa voi johtaa ohjelmakoodin sellaisen haaran suorittamiseen, jota ei normaaliolosuhteissa koskaan suoritettaisi [9] .
Esimerkiksi yllä oleva koodinpätkä voidaan suorittaa seuraavissa olosuhteissa:
Tällaisia ehtoja voi syntyä spontaanisti, mutta niitä voidaan muodostaa myös tarkoituksellisesti, esimerkiksi lukemalla suuri määrä ylimääräistä dataa, jotta prosessorin välimuisti täytetään näillä tiedoilla ja vastaavasti pudotetaan välimuistista array1_size ja array2 , ja kutsu sitten ydinfunktiota, joka käyttää salaista tavua k , jotta se tallennetaan välimuistiin. Jos välimuistin rakenne on kuitenkin tiedossa tai prosessori antaa vapaaehtoisesti välimuistin palautuskäskyn (esimerkiksi cflush -käsky x86 - perheprosessoreille ), niin koodifragmentin suorittamiseen tarvittavien ehtojen luominen yksinkertaistuu huomattavasti.
Koodinpätkä alkaa vertaamalla x :n arvoa taulukon1_koko arvoon . Matriisin 1_koko arvon lukeminen yllä kuvatuissa olosuhteissa johtaa välimuistin puuttumiseen, mikä puolestaan johtaa taulukon 1_koko arvon noutamiseen RAM-muistista. Prosessorissa olevan spekulatiivisen käskyn suoritusmekanismin vuoksi prosessori ei odotusajan aikana ole tyhjäkäynnillä, vaan yrittää suorittaa jonkin ohjelmakoodin haaroista haarakäskyn jälkeen.
Koska aiemmat pääsyt fragmenttiin suoritettiin kelvollisilla x :n arvoilla, haaraennustaja olettaa, että tällä kertaa predikaatti (x < array1_size) on tosi, ja prosessori yrittää suorittaa vastaavan käskysarjan. Se nimittäin lukee tavun osoitteessa <array1_address> + x , eli salaisen tavun k , joka erityisten muotoiltujen ehtojen ansiosta on jo välimuistissa. Sitten prosessori käyttää tuloksena olevaa arvoa lausekkeen k * 256 arvioimiseen ja taulukon taulukon 2 [k * 256] elementin lukemiseen , mikä aiheuttaa toisen välimuistin puuttumisen, ja odottaa, että taulukon 2[k * 256] arvo tulee näkyviin. haettu RAM-muistista. Tällä hetkellä RAM-muistista saadaan arvo array1_size , prosessori tunnistaa haaran ennustajan virheen ja palauttaa arkkitehtonisen tilan hetkeen ennen ohjelmakoodin virheellisen haaran suorittamisen alkamista.
Kuitenkin todellisissa prosessoreissa taulukon2[k * 256] spekulatiivinen luku vaikuttaa prosessorin välimuistin tilaan, ja tämä tila riippuu k :stä . Hyökkäyksen suorittamiseksi on tarpeen vain havaita tämä muutos käyttämällä sivukanavahyökkäystä (hyökkääjällä on oltava pääsy jaettuun prosessorin välimuistiin ja tarkkaan aikalähteeseen) ja laskea sen perusteella salainen tavu k . Tämä on helppo tehdä, koska taulukon 2 [n * 256] elementtien lukeminen on nopeaa n = k :lle ja hidasta muille arvoille.
Epäsuora haara voi käyttää useampaa kuin kahta osoitetta haarautumiseen. Esimerkiksi x86 -perheprosessorin käskyt voivat hypätä käyttämällä osoitearvoa rekisterissä ( jmp eax ), muistissa ( jmp [eax] tai jmp dword ptr [0xdeadc0de] ) tai pinossa ( ret ). Epäsuorat hyppyohjeet löytyvät myös ARM ( mov pc, r14 ), MIPS ( jr $ra ), SPARC ( jmpl %o7 ), RISC-V ( jarl x0,x1,0 ) ja monista muista.
Jos epäsuoran haaraosoitteen määrittäminen viivästyy välimuistin puuttumisen vuoksi ja epäsuoran haaran ennustaja "koulutetaan" erityisesti valituilla osoitteilla, voi tapahtua spekulatiivista käskyjen suorittamista hyökkääjän antamassa osoitteessa. Käskyt, joita ei muuten olisi koskaan toteutettu. Jos tällainen suoritus jättää mitattavissa olevia sivuvaikutuksia , sen käytöstä tulee tehokas työkalu hyökkääjän käsissä.
Tällä hetkellä ei ole olemassa valmiita ohjelmistoteknologioita suojaamaan Spectre-hyökkäystä vastaan, vaikka jonkin verran työtä tehdäänkin [10] . Hyökkäyksen edistämiseen omistetun verkkosivuston mukaan "Se ei ole niin helppoa korjata, ja se (virhe) kummittelee meitä pitkään."
Ohjelmistokorjaus voi sisältää ohjelmiston uudelleenkääntämisen käyttämällä uusia kääntäjiä haavoittuvien konekoodisekvenssien korvaamiseksi (ns. "retpoline"-mekanismi, toteutettu GCC :ssä ja Clang / LLVM :ssä ) [11] .
Prosessorivalmistajat ovat ehdottaneet useita korjauksia, joista osa vaatii prosessorin mikrokoodipäivityksiä, toiset uusien ohjeiden lisäämistä tuleviin prosessoreihin. Korjaukset tulisi yhdistää ohjelmistojen uudelleenkääntämiseen [11] .
Spectre CVE -ilmoituksen varhaisissa versioissa CERT ehdotti prosessorien vaihtamista vastauksena haavoittuvuuteen: "Haavoittuvuus johtuu valinnoista mikroprosessorisuunnittelussa. Haavoittuvuuden täydellinen poistaminen edellyttää mikroprosessorien vaihtamista." Myöhemmissä teksteissä tätä korjauksen versiota ei kuitenkaan enää mainittu [11] .