Kuinka puskurin alivuoto voi johtaa koodin etäsuorittamiseen 64-bittisellä?

Minulla on seuraava yhteenveto pseudokoodi C89: ssä ssh-palvelinkirjastosta, joka tarjoaa pääsyn vain esimerkiksi git-shelliin (/bin/bash korvataan suoritettavalla ohjelmalla, joten muuta ei voi tehdä) :

struct _raw_uncapped_ssh_string { // no limit on the size of the string; uint32_t len; char non_null_terminated_string[]; // by protocol design it have a minimum length of 1 }; typedef struct _raw_uncapped_ssh_string raw_ssh_string; union buffer { void * uncapped_zlib_decompressed_network_data; // yes, the size is uncapped, so it’s possible to put 4Gb of // data in it that would be copied later into memory. zlib // allow easily to turn some Mb in Gb of data, but it’s not // the point of the question. raw_ssh_string st; }; get_command (compressed_network_data) { size_t len; char * command; buffer string=uncompress_to_buffer(compressed_network_data); len=ntohl(string.st.len)+1; command=malloc(len+1); command[len]=0; // here’s the point, both the string length and content as // well it’s supplied size is controlled by the attacker. memcpy(command,string.st.data,len); return command; } 

Tässä on miten komento suoritetaan myöhemmin (merkkijono command ei muutu get_command()) jälkeen.

const char *args[]={"/bin/bash",command,NULL}; // /bin/bash isn’t the shell, it has been replaced by git‑shell. // redirect the program output to the network. dup2(stdin, 0); dup2(stdout,1); dup2(stdout,2); close(stdin); close(stdout); //if this return execution failed and print an error message return execv(args[0],(char * const *)args); // I don’t know which is the system, so I can’t know about the libc behaviour. 

En voi tehdä memcpy(command,string.st.data,0), koska ryhmän memcpy kolmannella jäsenellä on pienin koko 1, ja kontekstissani size_t käyttää 64-bittistä kokonaislukua, en voi suorittaa puskurin ylivuotoa, koska len.

Voin vain asettaa len arvoon, joka on suurempi kuin arvo, joka on varattu ryhmälle string.st.data. Tämä on puskurin alivuoto, jonka avulla voin lukea kohdistamatonta muistia.
Voin lukea palvelimen muistia, mutta en näe, mitä arkaluontoisia tietoja julkinen ssh-palvelin voi pitää sisällään (minun tapauksessani luettelo käyttäjistä, jotka voi suorittaa ssh on julkinen) .

Joten puskurin alivirta memcpy sallii etäyhteyden koodin suorittaminen?

Kommentit

  • Jos koodi todella tekee command[len] = 0 niin se on puskurin ylivuoto, koska puskurin, jonka pituus on len, enimmäisindeksi on len-1. Vaihtoehtoisesti, jos varsinainen koodi tekee malloc(len+1) malloc(len): n sijasta, voit tehdä massiivisen puskurin ylivuoton asettamalla len arvo arvoon 0xFFFFFFFF.
  • @ThomasPornin: Ei tämä ole minun osaltani virhe, itse asiassa se vaatii useita toimintoja Tämä. Oletetaan, että loput ovat totta.
  • @ThomasPornin: Puhun 64 bitistä, koska len on size_t, se käyttää 64 bitin kokonaislukua. Joten kokonaisluvun ylivuotoon ei ole mitään tapaa.
  • @ThomasPornin He varaavat len+1, joten asetuksen arvoksi 0 pitäisi olla kelvollinen.
  • @ RoraΖ: Hän puhui string.st.len -asetukseksi –1.

Vastaus

Yleensä ei, puskurin alivuotoa ei voida käyttää koodin etäsuorittamiseen. Koska hyökkääjän hallitsema data ei koskaan jätä sille varattua tilaa, sillä ei koskaan ole kykyä ottaa haltuunsa ohjelman suoritusta. tietojen paljastaminen (jos ohjelma luottaa siihen, että uudet tiedot pyyhkivät puskurin alkuperäisen sisällön).

Kommentit

  • Tai kuten minä näki äskettäin gitissä, muuttuu myöhemmin puskurin ylivuotoksi.

Vastaa

Kun kirjoitin tämän vastauksen alun perin , näyttää siltä, että olen hämmentänyt joitain väärinkäsityksiä, joita pidät. Nämä väärinkäsitykset estäisivät sinua todennäköisesti ymmärtämästä vastaustani. Selvyyden vuoksi aion tehdä tästä tekstistä suuren korostettavaksi, olematta epäkunnioittavaa:

Monet käyttämäsi termit eivät tarkoita sitä, mitä luulet niiden mielestä tarkoittavan.

Esimerkiksi:

  • memcpy kolmatta jäsentä ei ole, koska memcpy on funktio, ei struct tai union.
  • ”En voi suorittaa puskurin ylivuotoa, koska siellä on len enkä bensiini voi loppua, koska bensiiniä on. Kerronko kysymys? Minusta tuntuu sopivalta analogialta, varsinkin kun teoreettisesti puhuessasi koodi voisi kutsua puskurin ylivuotoa.
  • ”Voin vain asettaa len arvoon, joka on suurempi kuin arvo, joka on varattu ryhmälle string.st.data. Tämä on puskurin alivuoto … ” Ei, se ei ole puskurin alivirran määritelmä. Puskurin alivuoto tapahtuu, kun pääset matriisin ulkopuolelle negatiivisen indeksin tai indeksin avulla, joka aiheuttaisi jälkimmäinen saattaa olla mahdollista joillekin kokoonpanoille (jopa ”64-bittisissä järjestelmissä”, mitä se tarkoittaa), mutta epäilen, että tarkoitit tätä kirjoittaessasi näitä sanoja, koska seurasit niitä kanssa:
  • ”… antaa minulle mahdollisuuden lukea kohdentamatonta muistia.” Luulen, että tarkoitit ehkä ”alustamatonta muistia”. Selkeyden vuoksi mielestäni tarkoitit sanoa, että ”olemme jakaneet ylimäärän ja jättäneet ylimäärän alustamattomaksi , ja ehkä haluat tehdä asialle jotain (katso calloc tai memset

… tällaisella osoittimella on yleensä nolla arvo.Sen poikkeamista pidetään nollaosoittimen poikkeamana , mutta jos kirjoitamme jotain0["hello"], saamme saman kuin"hello"[0](eli"h"). Täten nollaosoittimen poikkeamista voidaan käyttää hyökkäyksissä, kun hyökkääjä hallitsee neliönmuotoisten aaltosulkeiden välistä lauseketta (kuten he tekevät tilanteessasi).

Palataan fubar juttu; sanotaan sanotaan, että memset(&fubar, UCHAR_MAX, sizeof fubar);, nyt fubar on kaikki 1-bittisiä, mikä tarkoittaa, että se voi olla osoite se on suurin osoite, johon järjestelmämme voisi (teoreettisesti) mahtua. Entä jos käytämme fubar[1]? Kuinka pääset elementtiin suurimman osoitteen jälkeen ? Teknisesti kaikki tämä on määrittelemätöntä käyttäytymistä, mutta jos nimittäisin sen yhteiselle arkkitehtuurille, se olisi:

  1. aritmeettinen ylivuoto osoitin, joka johtaa …
  2. Nolla osoittimen poikkeama ja / tai mahdollisesti puskurin alivirta .

sallii puskurin alivirta memcpy -palvelussa koodin etäsuorittamisen?

Puskuri alivuoto voi antaa hyökkääjälle mahdollisuuden korvata muistiosioilla olevat toiminnon osoittimet ennen kyseistä taulukkoa. Jos nämä toiminto-osoittimet tehdään osoittamaan kuorikoodiin, kyseinen kuorikoodi voi suoritetaan, kun niitä ”kutsutaan myöhemmin myöhemmin.

Tässä hieman hämärässä koodinpätkässä näyttää olevan puskurin alivuotoriski, kun int on verkkotunnus kuin uint32_t, koska ntohl(string.st.len)+1 aiheuttaisi uint32_t -arvon muuntamisen int -tyyppi. Harkitse esimerkiksi, jos INT_MIN on -4294967296 (mikä on yksi vähemmän kuin 0 - UINT32_MAX) ja INT_MAX on 4294967295 … tämä olisi olennaisesti 33-bittinen int pehmuste pehmustettavaksi tavun leveydelle; melko harvinaista, mutta mahdollista. Tässä tilanteessa lauseke ntohl(string.st.len)+1 ei ole uint32_t -tyyppi; se ”s int -tyyppinen ja sen sijaan, että kääritään takaisin 0: een, kun allekirjoittamaton kokonaisluvun ylivuoto tapahtuu, se todennäköisesti käärittyy -4294967296 kun allekirjoitettu kokonaisluvun ylivuoto tapahtuu.

Jos etsit takuuta puskurin alivuoto , käytä U kokonaisluku kirjaimellinen loppuliite (ts. ntohl(string.st.len)+1U). Silloin tässä tilanteessa lauseke on joko uint32_t tai unsigned int (riippuen siitä, minkä tyyppisellä on suurin verkkotunnus).

Jos katsot, että ntohl(string.st.len) voi palauttaa yhden alle kyseisen allekirjoittamattoman tyypin enimmäisarvon (mikä se sitten onkin), niin len=ntohl(string.st.len)+1 johtaa enimmäisarvoon, malloc(len+1) aiheuttaa allekirjoittamaton rivitys joten päädyt kutsumaan malloc(0) ja sitten command[len]=0 kirjoittaa hyvin ja aidosti taulukon lopun jälkeen. Sitten tietysti sinulla on ongelma memcpy(command,string.st.data,len);: n kanssa (tämä on puskurin ylivuoto).

Puskurin alivirrat ja ylivuoto ei ole ainoa riski. Jos et ”t tarkista paluuarvo malloc ja malloc palauttaa NULL, jolloin null-osoittimen poikkeamaa voidaan käyttää mielivaltaisen koodin suorittamiseen. Tämä tarkoittaa, että sinulla on oltava menetelmä kommunikoida malloc epäonnistuu takaisin soittajalle. Se tarkoittaa myös, että voit käyttää samaa tapaa tarkistaa ja välittää kääreongelma takaisin soittajalle.

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *