Prelivanje varovalnega prostora: vzroki, učinkovite metode za reševanje težave in potrebna zaščita

Vsi programerji se zavedajo potencialne nevarnosti, ki jo v njihovih programih predstavlja prelivanje medpomnilnika. Ne glede na število popravkov je z njo povezanih veliko groženj, tako v novi kot v stari programski opremi. Napadalci lahko to napako izkoristijo tako, da v začetni del niza podatkov vnesejo kodo, ki je posebej zasnovana tako, da povzroči prelivanje, nato pa preostanek podatkov zapišejo na pomnilniški naslov, ki je v bližini preliva.

Podatki lahko vsebujejo izvršljivo kodo, ki napadalcem omogoča zagon večjih in kompleksnejših programov ali dostop do sistema. Hrošča je zelo težko najti in odpraviti, saj je programska koda sestavljena iz milijonov vrstic. Popravljanje teh napak je težavno in nagnjeno k napakam, zato je težko.

Zaznavanje prelivanja medpomnilnika

Zaznavanje prelivanja medpomnilnika

Preden poiščete preliv, morate vedeti, Kaj je. Kot pove že ime, so te ranljivosti povezane s predpomnilniki ali dodeljevanjem pomnilnika v jezikih, ki omogočajo neposreden dostop na nizki ravni za branje in pisanje.

V jezikih C in Assembler branje ali pisanje takšnih dodelitev ne vključuje samodejnega preverjanja mej. Če je v določeni aplikaciji odkrito prelivanje zalogovnega predpomnilnika, se torej ne preveri, ali je v zadevni predpomnilnik mogoče namestiti določeno število bajtov. V takih primerih lahko program "preseže" svoje zmogljivosti. To povzroči, da podatki, zapisani po polnjenju, prepišejo vsebino naslednjih naslovov na nizu in preberejo dodatne. Do prelivanja lahko pride nenamerno zaradi napak uporabnika.

To lahko povzroči zlonamerni akter, ki pošlje skrbno pripravljen zlonamerni vnos programu, ki ga nato poskuša shraniti v nezadostno velik medpomnilnik. Če je v tej aplikaciji zaznana prelivanje zalogovnega predpomnilnika, se odvečni podatki zapišejo v sosednji predpomnilnik, kjer prepišejo vse obstoječe podatke.

Običajno vsebujejo povratni kazalec na izkoriščano funkcijo - naslov, kam mora proces iti naprej. Napadalec lahko nove vrednosti nastavi tako, da kažejo na izbrani naslov. Napadalec običajno nastavi nove vrednosti, ki označujejo, kje se nahaja koristni tovor. To spremeni pot izvajanja procesa in takoj prenese nadzor na zlonamerno kodo.

Z uporabo prelivanja medpomnilnika lahko napadalec nadzoruje ali prekine proces ali spremeni njegove notranje spremenljivke. Ta ranljivost spada med 25 najnevarnejših programskih napak na svetu (2009 CWE/SANS Top 25 Most Dangerous Programming Errors) in je v Slovarju sistemskih ranljivosti opredeljena kot CWE-120. Čeprav so dobro raziskane, še vedno pestijo priljubljene programe.

Enostavni vektor uporabe predpomnilnika

Pri delu z izvorno kodo je treba posebno pozornost nameniti temu, kje se uporabljajo in spreminjajo predpomnilniki. Posebej je treba omeniti funkcije, ki se nanašajo na vnos, ki ga zagotovi uporabnik ali drug zunanji vir, saj zagotavljajo preprost vektor, ki se uporabi, ko se odkrije prelivanje skladiščnega predpomnilnika. Na primer, ko uporabnik postavi vprašanje "da" ali "ne", je primerno, da se podatki o uporabnikovem nizu shranijo v majhnem bufferju za niz "da", kot je prikazano v naslednjem primeru.

Preprost vektor za uporabo bufferja

Če pogledate kodo, lahko vidite, da se ne izvede noben mejni pregled. Če uporabnik vnese "morda", se program raje sesuje, kot da bi zahteval odgovor, ki se zapiše v medpomnilnik ne glede na dolžino. Ker je v tem primeru odgovor uporabnika edina deklarirana spremenljivka, bo naslednja vrednost na kupu vrednost povratnega naslova ali pomnilniške lokacije, na katero se bo program vrnil po izvedbi funkcije vprašati vprašanje.

To pomeni, da če uporabnik vnese štiri bajte podatkov, kar je dovolj, da se zapolni odjemalčev buffer za navodila, bo sledil veljaven povratni naslov, ki se bo spremenil. To povzroči, da program zaključi funkcijo na drugi točki v kodi, kot je bilo prvotno predvideno, kar lahko povzroči nevarno in nenamerno obnašanje programske opreme.

Če je prvi korak za odkrivanje prelivov predpomnilnika v izvorni kodi razumevanje njihovega delovanja, je drugi korak pregled zunanjega vnosa in manipulacije s predpomnilnikom, tretji korak pa je ugotoviti, katere funkcije so ranljive za to ranljivost in katere lahko delujejo kot "rdeče zastavice". Funkcija gets je odlična za pisanje zunaj bufferja, ki ji je na voljo. Pravzaprav se ta lastnost razširi na celotno družino sorodnih funkcij, vključno s strcpy, strcmp in printf/sprintf, kadar koli je uporabljena ena od teh ranljivosti prelivanja.

Odstranitev iz baze kode

Če je v izvorni kodi odkrito prelivanje zalogovnega predpomnilnika, ga je treba dosledno odstraniti iz osnove. Poznati je treba varne prakse. Te ranljivosti najlažje preprečite tako, da uporabite jezik, ki ne. Jezik C ima te ranljivosti zaradi neposrednega dostopa do pomnilnika in pomanjkanja strogega tipiziranja objektov. Jeziki, ki nimajo teh vidikov, so običajno nezaščiteni. To so Java, Python in .NET ter druge jezike in platforme, ki ne zahtevajo posebnih preverjanj ali sprememb.

Seveda ni vedno mogoče popolnoma spremeniti razvojnega jezika. V tem primeru se uporabljajo varne metode delati prelivanje medpomnilnika ukaza. V primeru funkcij nizov je bilo veliko razprav o tem, katere metode so na voljo, katere je varno uporabljati in katerih se je treba izogibati. Funkciji strcpy in strcat kopirata niz v buffer in dodajata vsebino enega v drugega. Ti dve metodi se obnašata nevarno, ker ne preverjata meja ciljnega medpomnilnika in pišeta zunaj meja, če je za to dovolj bajtov.

Alternativna zaščita

Pogosto predlagana alternativa so vezane različice, ki zapisujejo v največjo velikost ciljnega predpomnilnika. Na prvi pogled se zdi, da je to idealna rešitev. Na žalost imajo te funkcije majhno nianso, ki povzroča težave. Ko je meja dosežena, če zaključni znak ni v zadnjem bajtu, se se zruši, ko branje varovalnega mehanizma.

Alternativna zaščita

V tem poenostavljenem primeru lahko vidimo nevarnosti nizov, ki se ne končajo z ničlo. Ko je foo postavljen v običajni buffer, se zaključi na nič, ker ima dodaten prostor. To je najboljši možni scenarij. Če so bajti v prepolnem predpomnilniku na kupu v drugem znakovnem nizu ali drugem tiskljivem nizu, bo funkcija tiskanja nadaljevala z branjem, dokler ne bo dosežen zadnji znak tega niza.

Pomanjkljivost je, da jezik C ne ponuja standardne in varne alternative tem funkcijam. Kljub temu ima to tudi pozitivno plat - na voljo je več izvedb za posamezne platforme. OpenBSD ponuja strlcpy in strlcat, ki delujeta podobno kot strn, le da skrajšata niz za en znak prej, da prostor za ničelni terminator.

Podobno Microsoft zagotavlja lastne varne izvedbe pogosto uporabljenih funkcij za obdelavo nizov: strcpy_s, strcat_s in sprintf_s.

Raje uporabite zgoraj navedene varne alternative. Če to ni mogoče, se med obdelavo predpomnilnikov nizov izvede ročno preverjanje mej in ničelno zaključevanje.

Ranljivosti pri sestavljanju

Ranljivosti pri sestavljanju

Če nezanesljiva funkcija pušča odprto možnost za prelivanje medpomnilnika C, še ni vse izgubljeno. Prevajalniki med izvajanjem programa pogosto ustvarijo naključne vrednosti, znane kot kanarčki, in jih postavijo na kup, zato so nevarne. S preverjanjem vrednosti kanarčka glede na prvotno vrednost lahko ugotovite, ali je prišlo do prepolnitve predpomnilnika sistema Windows. Če je bila vrednost spremenjena, se program zapre ali preide v stanje napake namesto na morebitni spremenjeni povratni naslov.

Nekateri sodobni operacijski sistemi zagotavljajo dodatno zaščito pred prelivanjem medpomnilnika v obliki neizvedljivih nizov in naključnega razporejanja naslovnega prostora (ASLR). Neizvedljivi skladi - preprečevanje izvajanja podatkov (DEP) - označuje sklad in v nekaterih primerih tudi druge strukture kot območja, kjer se koda ne bo izvajala. To pomeni, da napadalec ne more vnesti izkoriščevalske kode v sklad in pričakovati, da se bo uspešno izvedla.

Pred popravljanjem prelivanja medpomnilnika razpakirajte ASLR v računalniku. Zasnovan je bil za zaščito pred programiranjem, usmerjenim v vračanje, kot rešitev za neizvedljive skladove, pri katerih so obstoječi deli kode verižno povezani skupaj na podlagi njihovih odmikov naslovov.

Deluje tako, da naključno spreminja pomnilniške regije struktur, tako da je njihove odmike težje določiti. Če bi ta zaščita obstajala konec osemdesetih let prejšnjega stoletja, bi se lahko izognili črvu Morris. Deluje namreč tako, da delno napolni buffer v protokolu UNIX finger finger s kodo za izkoriščanje, nato pa ga prepolni, da spremeni povratni naslov in pokaže na napolnjen buffer.

ASLR in DEP sta otežila določanje naslova, na katerega je treba pokazati, zaradi česar je bilo to območje pomnilnika popolnoma neuporabno. Včasih se zgodi, da se ranljivost izmuzne skozi razpoke, ki so odprte za napad s prelivanjem medpomnilnika, kljub prisotnosti nadzora na ravni razvoja, prevajalnika ali operacijskega sistema.

Statična analiza pokritosti

V primeru prelivanja se pojavljata dve odločilni težavi. Najprej moramo ugotoviti ranljivost in spremeniti kodo za rešitve problema. Drugič, nadomešča vse različice kode ranljivosti zaradi prelivanja varovalnega prostora. Najbolje bi bilo, če bi se to začelo s samodejno posodobitvijo vseh sistemov, povezanih z internetom.

Ni mogoče domnevati, da bo takšna posodobitev zagotavljala zadostno pokritost. Organizacije ali posamezniki lahko uporabljajo programsko opremo v sistemih z omejenim dostopom do interneta, ki zahtevajo ročno posodabljanje. To pomeni, da je treba novico o posodobitvi posredovati vsem skrbnikom, ki morda uporabljajo programsko opremo, popravek pa mora biti takoj na voljo za prenos. Ustvarjanje in distribucijo popravkov je treba opraviti čim prej po odkritju ranljivosti, da se čim bolj skrajša čas ranljivosti.

Z uporabo funkcij za varno ravnanje z medpomnilnikom in ustreznih varnostnih funkcij prevajalnika ter operacijski sistem je mogoče ustvariti zanesljivo zaščito pred preobremenitvijo. Glede na te korake je dosledno prepoznavanje pomanjkljivosti ključni korak za preprečevanje izkoriščanja.

Združevanje vrstic izvorne kode za iskanje morebitnih groženj je lahko zamudno. Poleg tega vedno obstaja možnost, da človeško oko spregleda kaj pomembnega. Orodja za statično analizo se uporabljajo za zagotavljanje kakovosti kode in so bila razvita posebej za odkrivanje varnostnih ranljivosti med razvojem.

Statična analiza pokritosti določa "rdeče zastave" za morebitne prelive medpomnilnika. Nato se obravnavajo in popravljajo ločeno, tako da jih ni treba ročno iskati v zbirki podatkov. Ta orodja v kombinaciji z rednimi pregledi in znanjem o tem, kako odpraviti prelive, omogočajo, da veliko večino napak odkrijete in odpravite, še preden je razvoj programske opreme končan.

Izvedba napada prek korenskega uporabnika

Napake pri kodiranju so običajno vzrok za prelivanje kode. Pogosti hrošči pri razvoju aplikacij, ki lahko privedejo do tega, vključujejo nezmožnost dodelitve dovolj velikih predpomnilnikov in pomanjkanje mehanizma za preverjanje teh težav. Te napake so še posebej problematične v jezikih C/C++, ki nimajo vgrajene zaščite pred prelivanjem medpomnilnika in so pogosto tarča napadov s prelivanjem medpomnilnika.

V nekaterih primerih napadalec vnese zlonamerno kodo v pomnilnik, ki je bil poškodovan s prenapolnjenim zalogovnikom. V drugih primerih preprosto izkoristi poškodbe sosednjega pomnilnika. Na primer program, ki od uporabnika zahteva geslo, da bi mu omogočil dostop do sistema. V spodnji kodi pravilno geslo podeljuje privilegije root. Če je geslo napačno, program uporabniku ne dodeli pravic.

Program ne podeli uporabniških privilegijev

V zgornjem primeru bi program uporabniku dodelil pravice korporacije root, tudi če bi vnesel napačno geslo. V tem primeru vsiljivec zagotovi vhodni podatek z dolžino, ki je večja, kot jo lahko sprejme predpomnilnik, kar povzroči prelivanje in prepiše pomnilnik celoštevilskega prehoda. Zato kljub neveljavnemu geslu pass postane neničelna vrednost in napadalec dobi pravice root.

Napad na območje začasnega shranjevanja

Buffer je začasno območje za shranjevanje podatkov. Ko program ali sistemski proces vnese več podatkov, kot jih je bilo prvotno dodeljenih za shranjevanje, pride do prelivanja dodatnih podatkov. Zaradi tega nekatere od njih uhajajo v druge datoteke in poškodujejo ali prepišejo podatke.

Pri poplavnem napadu dodatni podatki vsebujejo posebna navodila za dejanja, ki jih namerava izvesti heker ali zlonamerni uporabnik, na primer sprožitev odziva, ki poškoduje datoteke, spremeni podatke ali razkrije osebne podatke.

Napadalec z izkoriščanjem prelivanja izkoristi program, ki čaka na uporabniški vnos. Poznamo dve vrsti prelivanja medpomnilnika: na osnovi kupa in na osnovi kupa. Na kupu temelječe programe je težko izvesti in so najmanj pogosti, medtem ko napadajo aplikacijo in zapolnjujejo prostor, rezerviran za program.

Sklad je pomnilniški prostor, ki se uporablja Shranjevanje uporabnika vnos. Na to vrsto prelivanja bodo napadalci najverjetneje naleteli pri uporabi aplikacij.

Sodobni prevajalniki običajno omogočajo preverjanje prelivanja v času sestavljanja/kompiliranja, vendar je med izvajanjem precej težko preveriti to težavo brez dodatnega zaščitnega mehanizma za ravnanje z izjemami.

Izvedba napada prek korenskega uporabnika

Variante delovanja programa:

  1. Vnos: 12345678 (8 bajtov), program deluje brez težav.
  2. Vnesite: 123456789 (9 bajtov), pojavi se sporočilo "Segmentation error", program se zaključi.

Ranljivost obstaja zaradi prepolnitve, če uporabniški vnos argv preseže 8 bajtov. Za 32-bitni sistem (4 bajti) napolnite pomnilnik z dvojno besedo (32 bitov). Velikost znaka je 1 bajt, zato bo sistem, če zahtevate 5-bajtni buffer, dodelil 2 dvojni besedi (8 bajtov). Zato bo vnos več kot 8 bajtov povzročil, da se bo buffer prepolnil.

Obstajajo podobne standardne funkcije, ki so tehnično manj ranljive. Na primer strncpy (), strncat () in memcpy (). Težava teh funkcij je, da, to odgovornost Za določitev velikosti predpomnilnika je odgovoren programer in ne prevajalnik.

Vsak programer v jeziku C/C++ bi se moral pred začetkom kodiranja zavedati te težave. Veliko ustvarjenih težav je v večini primerov mogoče zaščititi pred prelivanjem.

Nevarnosti v C/C++

http://blogs.grammatech.com/eliminating-the-danger-of-uninitialized-variables

Uporabniki C naj se izogibajo uporabi nevarnih funkcij, ki ne preverjajo mej, razen če so prepričani, da meje ne bodo presežene. Funkcije, ki se jim je treba v večini primerov izogibati, da bi zagotovili zaščito, vključujejo funkcije strcpy. Nadomestiti jih je treba s funkcijami, kot so strncpy. Uporabi strlen se je treba izogniti, če je uporabnik prepričan, da bo našel zaključni znak NIL. Družina scanf (): scanf (3), fscanf (3), sscanf (3), vscanf (3), vsscanf (3) in vfscanf (3) je nevarna za uporabo in se ne uporablja za pošiljanje podatkov v niz brez nadzora največje dolžine, "format% s" je še posebej pogosta napaka.

Uradno snprintf () ni standardna funkcija C po klasifikaciji ISO 1990. Ti sistemi ne ščitijo pred prepolnitvijo bufferja, temveč samo neposredno kličejo sprintf. Znano je, da trenutna različica sistema Linux snprintf deluje pravilno, to pomeni, da dejansko upošteva mejo. Spremeni se tudi povratna vrednost funkcije snprintf ().

Različica 2 specifikacije Unix (SUS) in standard C99 se razlikujeta po tem, da vračata snprintf (). Nekatere različice programa snprintf ne zagotavljajo, da se niz konča z NIL, in če je niz predolg, sploh ne vsebuje NIL. Knjižnica glib ima g_snprintf () s konsistentno semantiko vračanja, ki se vedno konča z NIL in, kar je najpomembneje, vedno upošteva dolžino bufferja.

Prelivanje medpomnilnika komunikacijskih vrat

Prelivanje medpomnilnika komunikacijskih vrat

Občasno se zgodi, da serijska vrata poročajo o prepolnitvi medpomnilnika. Ta težava je lahko posledica več dejavnikov. Ti vključujejo hitrost računalnika, hitrost prenosa podatkov, velikost FIFO zaporednih vrat in velikost FIFO naprave, ki pošilja podatke v zaporedna vrata.

Nadzor pretoka bo počakal, da bo v predpomnilniku določeno število bajtov, preden bo procesor drugi napravi poslal sporočilo ali signal za prekinitev prenosa. Pri višjih prenosnih hitrostih bodo serijska vrata prejela več bajtov od trenutka, ko bo dosežena raven nadzora pretoka v predpomnilniku in bo naprava prenehala oddajati.

Teh dodatnih bajtov bo več, če ciljni procesor v realnem času nadzoruje proces z visoko prioriteto. Ker ima proces prepolnitve predpomnilnika komunikacijskih vrat višjo prioriteto kot prekinitev VISA, procesor ne bo ukrepal, dokler se takšna prekinitev ne zaključi v realnem času.

Privzeta nastavitev VISA in Windows za 16-bajtni FIFO je 14 bajtov, kar pomeni, da v FIFO ostaneta 2 bajta, ko naprava poskuša poslati sporočilo iz vira. Pri višjih prenosnih hitrostih na počasnejših računalnikih je mogoče dobiti več kot 4 bajte, ko zaporedna vrata poizvedujejo po procesorju in pošljejo signal za prekinitev prenosa.

Če želite rešiti težavo, ko je v sistemu Windows 10 zaznano prelivanje skladiščnega predpomnilnika, morate odpreti Upravitelja naprav. Nato poiščite vrata COM, katerih nastavitve so spremenjene, in odprite njihove lastnosti. Nato kliknite na zavihek "Napredno", pojavi se drsnik, ki bo spremenil velikost prelivanja medpomnilnika, tako da bo UART hitreje vklopil nadzor pretoka.

Privzeta vrednost je v večini primerov dovolj. Če pride do napake prelivanja medpomnilnika, zmanjšajte vrednost. To bo povzročilo več prekinitev, ki bodo poslane procesorju s počasnejšimi bajti na UART.

Varne razvojne metode

Tehnike varnega razvoja

Tehnike varnega razvoja vključujejo redno testiranje za odkrivanje in odpravljanje prelivov. Najzanesljivejši Lahko se jim izognete ali jih preprečite tako, da uporabite samodejno zaščito na ravni jezika. Druga rešitev je preverjanje meja med izvajanjem, ki preprečuje prelivanja s samodejnim preverjanjem, ali so podatki, zapisani v medpomnilnik, znotraj sprejemljivih meja.

Storitev v oblaku Veracode prepoznava ranljivosti kode, kot so prelivi medpomnilnika, tako da jih razvijalci odpravijo, še preden so izkoriščene. Veracodejeva edinstvena patentirana tehnologija za testiranje varnosti binarnih statičnih aplikacij (SAST) jih analizira, vključno z odprtokodnimi komponentami in komponentami tretjih oseb, ne da bi zahtevala dostop do njih.

SAST dopolnjuje modeliranje groženj in preglede kode, ki jih izvajajo razvijalci, ter z avtomatizacijo hitreje in ceneje odkriva napake in pomanjkljivosti v kodi. Običajno se začne na začetku življenjskega cikla razvoja programske opreme, saj je lažje in ceneje odpraviti težave, preden se uvede v produkcijo.

SAST identificira kritične ranljivosti, kot so vbrizgavanje SQL, navzkrižno pisanje skriptov (XSS), napaka prelivanja medpomnilnika, neobdelane napake in morebitni kotički. Poleg tega binarna tehnologija SAST zagotavlja koristne informacije, ki določajo prednost glede na resnost in zagotavljajo podrobna navodila sanacija.

Ranljivost buffer overflow obstaja že skoraj tri desetletja, vendar je še vedno obremenjujoča. Zaradi velikega števila dovzetnih spletnih aplikacij ga hekerji po vsem svetu še vedno obravnavajo kot privzeto taktiko. Razvijalci in programerji si zelo prizadevajo za boj proti temu IT zlu in izumljajo vedno več načinov, kako.

Osnovna zamisel slednjega pristopa je izvajanje orodja za sanacijo, ki naredi več kopij povratnega naslova v nizu in nato naključno določi lokacijo vseh kopij, poleg števila. Vse podvojitve se posodabljajo in preverjajo vzporedno, zato vsako neskladje med njimi pomeni možen poskus napada in sproži izjemo.

Članki na tem področju