Buffer overflow

Versiunea actuală a paginii nu a fost încă revizuită de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 6 ianuarie 2017; verificările necesită 22 de modificări .

Un  buffer overflow este un fenomen care apare atunci când un program de calculator scrie date în afara unui buffer alocat în memorie .

Depășirile de buffer rezultă de obicei din manipularea necorespunzătoare a datelor și memoriei primite extern, în absența unor protecții puternice din partea subsistemului de programare ( compilator sau interpret ) și a sistemului de operare . Ca urmare a unui overflow, datele situate după buffer (sau înaintea acestuia) [1] pot fi corupte .

Buffer overflow este una dintre cele mai populare moduri de a pirata sistemele informatice [2] , deoarece majoritatea limbajelor de nivel înalt folosesc tehnologia stack frame  - plasarea datelor pe stiva de proces , amestecarea datelor programului cu datele de control (inclusiv adresa de început a stivei). cadru stivă și adresa de retur de la funcția executabilă).

O depășire a memoriei tampon poate cauza blocarea sau blocarea unui program, ceea ce duce la refuzul serviciului ( DoS). Anumite tipuri de overflow, cum ar fi un stack frame overflow, permit unui atacator să încarce și să execute cod de mașină arbitrar în numele programului și cu drepturile contului de pe care rulează [3] .

Sunt cunoscute exemple când depășirile de buffer sunt utilizate în mod deliberat de programele de sistem pentru a evita limitările din software-ul sau firmware-ul existent. De exemplu, sistemul de operare iS-DOS (pentru calculatoarele ZX Spectrum ) a folosit caracteristica de depășire a tamponului a TR-DOS încorporat pentru a- și lansa bootloader -ul în coduri de mașină (ceea ce este imposibil de realizat cu instrumentele standard TR-DOS).

Securitate

Un program care folosește o vulnerabilitate pentru a rupe protecția unui alt program se numește exploit . Cele mai periculoase sunt exploit-urile concepute pentru a obține acces la nivelul de superutilizator sau, cu alte cuvinte, escaladarea privilegiilor . Exploatarea buffer overflow realizează acest lucru prin transmiterea unei intrări special concepute în program. Astfel de date depășesc bufferul alocat și modifică datele care urmează acelui buffer în memorie . [patru]

Imaginați-vă un program ipotetic de administrare a sistemului care rulează cu privilegii de superutilizator, de exemplu, schimbarea parolelor utilizatorului . Dacă programul nu verifică lungimea noii parole introduse, atunci orice date care depășește dimensiunea bufferului alocat pentru stocarea lor vor fi pur și simplu scrise peste ceea ce a fost după buffer. Un atacator poate introduce instrucțiuni în limbajul mașinii în această zonă de memorie , de exemplu, shellcode , efectuând orice acțiune cu privilegii de superutilizator - adăugarea și ștergerea conturilor de utilizator, schimbarea parolelor, modificarea sau ștergerea fișierelor etc. Dacă este executat în această zonă de memorie este permis și în pe viitor, programul îi va transfera controlul, sistemul va executa codul de mașină al atacatorului aflat acolo.

Programele bine scrise ar trebui să verifice lungimea datelor de intrare pentru a se asigura că nu este mai mare decât bufferul de date alocat. Cu toate acestea, programatorii uită adesea de asta. Dacă buffer-ul este situat pe stivă și stiva „crește în jos” (de exemplu, în arhitectura x86 ), atunci folosind un buffer overflow, puteți modifica adresa de retur a funcției executate , deoarece adresa de retur este situată după buffer alocat de funcția executată. Astfel, este posibil să se execute o secțiune arbitrară a codului mașină în spațiul de adrese al procesului. Este posibil să se folosească un buffer overflow pentru a deteriora adresa de retur chiar dacă stiva „crește” (caz în care adresa de retur este de obicei înaintea bufferului). [5]

Chiar și programatorilor cu experiență le este dificil să stabilească dacă o anumită depășire a memoriei tampon ar putea fi o vulnerabilitate. Acest lucru necesită cunoaștere profundă a arhitecturii computerului și a programului țintă. S-a demonstrat că chiar și depășirile mici precum scrierea unui singur octet din buffer pot reprezenta vulnerabilități. [6]

Depășirile de buffer sunt frecvente în programele scrise în limbaje de programare de nivel relativ scăzut, cum ar fi limbajul de asamblare , C și C++ , care necesită programator să controleze dimensiunea memoriei alocate. Depanarea depășirii tamponului este încă un proces prost automatizat. Sistemele formale de verificare a programelor nu sunt foarte eficiente cu limbajele de programare moderne. [7]

Multe limbaje de programare, cum ar fi Perl , Python , Java și Ada , gestionează automat alocarea memoriei, făcând erorile de depășire a memoriei tampon improbabile sau imposibile. [8] Perl oferă redimensionarea automată a matricelor pentru a evita depășirile de buffer . Cu toate acestea, sistemele de rulare și bibliotecile pentru astfel de limbi pot fi încă susceptibile la depășiri de buffer din cauza posibilelor erori interne în implementarea acestor sisteme de validare. Pe Windows sunt disponibile mai multe soluții software și firmware care împiedică executarea codului în afara unui buffer de overflow dacă are loc o astfel de depășire. Aceste soluții includ DEP în Windows XP SP2 , [9] OSsurance și Anti-Execute .

În arhitectura Harvard , codul executabil este păstrat separat de date, ceea ce face ca astfel de atacuri să fie aproape imposibile. [zece]

Scurt rezumat tehnic

Exemplu

Luați în considerare un exemplu de program C vulnerabil :

#include <șir.h> int main ( int argc , char * argv []) { charbuf [ 100 ] ; strcpy ( buf , argv [ 1 ]); returnează 0 ; }

Folosește funcția unsafe strcpy , care vă permite să scrieți mai multe date decât pot încăpea în matricea alocată pentru acestea. Dacă rulați acest program pe un sistem Windows cu un argument care este mai lung de 100 de octeți, cel mai probabil programul se va bloca și utilizatorul va primi un mesaj de eroare.

Următorul program nu este afectat de această vulnerabilitate:

#include <șir.h> int main ( int argc , char * argv []) { charbuf [ 100 ] ; strncpy ( buf , argv [ 1 ], sizeof ( buf )); returnează 0 ; }

Aici, strcpy a fost înlocuit cu strncpy , unde numărul maxim de caractere de copiat este limitat de dimensiunea bufferului. [unsprezece]

Descriere

Diagramele de mai jos arată cum un program vulnerabil poate deteriora structura stivei .

Ilustrație a scrierii diferitelor date într-un buffer alocat pe stivă

În arhitectura x86 , stiva crește de la adrese mai mari la cele mai mici, adică noile date sunt plasate înaintea celor care sunt deja pe stivă.

Scriind date în buffer, puteți scrie dincolo de limitele acestuia și puteți modifica datele acolo, în special, modificați adresa de retur .

Dacă programul are privilegii speciale (cum ar fi rularea ca root ), un atacator poate schimba adresa de retur cu o adresă shellcode , permițându-i să execute comenzi pe sistemul țintă cu privilegii ridicate . [12]

Exploatarea

Tehnicile de depășire a memoriei tampon variază în funcție de arhitectură, sistemul de operare și zona de memorie. De exemplu, cazul unui buffer overflow pe heap (utilizat pentru alocarea dinamică a memoriei) este semnificativ diferit de cel de pe stiva de apeluri .

Exploatarea stivei

Cunoscut și sub numele de spargerea stivei . Un utilizator experimentat în tehnologie poate folosi un buffer overflow pentru a manipula programul în avantajul său în următoarele moduri:

  • suprascrierea unei variabile locale situate în memorie lângă buffer, schimbând comportamentul programului în favoarea acestuia.
  • suprascrierea adresei de retur în cadrul stivei . Imediat ce funcția se termină, controlul este transferat la adresa specificată de atacator, de obicei în zona de memorie pe care a avut acces să o modifice.
  • suprascrierea unui indicator de funcție [13] sau a unui handler de excepții care va prelua ulterior controlul.
  • suprascrierea parametrului dintr-un alt cadru de stivă sau o adresă non-locală indicată în contextul curent. [paisprezece]

Dacă adresa datelor utilizatorului este necunoscută, dar este stocată într- un registru, se poate folosi metoda trambulinei   :  adresa de retur poate fi suprascrisă cu adresa opcode-ului , care va transfera controlul în zona de memorie cu datele utilizatorului. Dacă adresa este stocată în registrul R, atunci săriți la o comandă care transferă controlul către acea adresă (de exemplu, apelul R) va determina executarea codului specificat de utilizator. Adresele codurilor operaționale adecvate sau octeții de memorie pot fi găsite în DLL sau în executabilul însuși. Cu toate acestea, adresele de obicei nu pot conține caractere nule, iar locațiile acestor coduri operaționale variază în funcție de aplicație și sistemul de operare. Proiectul Metasploit , de exemplu, a menținut o bază de date cu coduri operaționale adecvate pentru sistemele Windows (care este momentan indisponibilă). [cincisprezece]

O depășire a stivei nu trebuie confundată cu o depășire a stivei .

De asemenea, este de remarcat faptul că astfel de vulnerabilități sunt de obicei găsite folosind tehnica de testare fuzzing .

Exploatarea heap

Un buffer overflow într-o zonă de date heap se numește heap overflow și este exploatat într-un mod diferit decât un buffer overflow în stivă. Memoria heap este alocată dinamic de o aplicație în timpul rulării și de obicei conține date de program. Exploatarea se face prin coruperea acestor date în moduri speciale pentru a forța aplicația să suprascrie structuri interne, cum ar fi pointerii în listele legate. O tehnică obișnuită de exploatare pentru depășirile buffer-ului heap este de a suprascrie referințe de memorie dinamică (cum ar fi metadatele funcției malloc ) și de a utiliza pointerul modificat rezultat pentru a suprascrie indicatorul de funcție a programului.

O vulnerabilitate în produsul Microsoft GDI+ în manipularea imaginilor JPEG  este un exemplu al pericolului pe care îl poate reprezenta o depășire a memoriei tampon. [16]

Dificultăți în funcționare

Manipularea bufferului înainte de a-l citi sau de a-l executa poate preveni exploatarea cu succes a vulnerabilității. Ele pot reduce amenințarea unui atac de succes, dar nu o pot elimina complet. Acțiunile pot include conversia unui șir în majuscule sau litere mici, eliminarea caracterelor speciale sau filtrarea tuturor caracterelor, cu excepția caracterelor alfanumerice. Cu toate acestea, există trucuri pentru a ocoli aceste măsuri: coduri shell alfanumerice, [17] coduri polimorfe , [ 18 ] coduri auto - schimbabile și atacul de întoarcere a bibliotecii . [19] Aceleași tehnici pot fi folosite pentru a se ascunde de sistemele de detectare a intruziunilor . În unele cazuri, inclusiv cazurile de conversie a caracterelor în Unicode , vulnerabilitatea este confundată cu permiterea unui atac DoS , când de fapt este posibilă executarea de la distanță a unui cod arbitrar. [douăzeci]

Prevenirea

Sunt folosite diverse trucuri pentru a reduce probabilitatea depășirilor de buffer.

Sisteme de detectare a intruziunilor

Sistemele de detectare a intruziunilor (IDS) pot detecta și preveni încercările de a exploata de la distanță depășirile de buffer. Deoarece în majoritatea cazurilor datele destinate unei depășiri de buffer conțin șiruri lungi de instrucțiuni No Operation ( NOPsau ) NOOP, IDS pur și simplu blochează toate pachetele primite care conțin un număr mare de NOP-uri consecutive. Această metodă este în general ineficientă, deoarece astfel de matrice pot fi scrise folosind o varietate de instrucțiuni în limbaj de asamblare . Mai recent, crackerii au început să folosească coduri shell cu criptare , cod auto-modificabil , cod polimorf și cod alfanumeric , precum și atacuri de rezervă la biblioteca standard pentru a pătrunde IDS. [21]

Protecție împotriva corupției stivei

Protecția împotriva corupției stivei este utilizată pentru a detecta cele mai frecvente erori de depășire a tamponului. Aceasta verifică dacă stiva de apeluri nu a fost modificată înainte de a reveni din funcție. Dacă a fost schimbat, atunci programul se termină cu o eroare de segmentare .

Există două sisteme, StackGuard și Stack-Smashing Protector (fostul ProPolice), ambele extensii ale compilatorului gcc . De la gcc-4.1-stage2, SSP a fost integrat în distribuția principală a compilatorului . Gentoo Linux și OpenBSD includ SSP cu distribuțiile lor gcc. [22]

Plasarea adresei de retur pe stiva de date facilitează implementarea unui buffer overflow care duce la execuția arbitrară a codului. Teoretic, s-ar putea face modificări la gcc pentru a permite ca adresa să fie plasată pe o stivă specială de returnare care este complet separată de stiva de date, similar modului în care este implementată în limbajul Forth . Cu toate acestea, aceasta nu este o soluție completă la problema depășirii tamponului, deoarece și alte date din stivă trebuie protejate.

Protecția spațiului de cod pentru sisteme asemănătoare UNIX

Protejarea spațiului de cod executabil poate atenua efectele depășirilor de buffer, făcând imposibile majoritatea acțiunilor rău intenționate. Acest lucru se realizează prin randomizarea spațiului de adrese ( ASLR ) și/sau interzicerea accesului simultan la memorie pentru scriere și execuție. Stiva care nu poate fi executată previne majoritatea exploit- urilor de cod shell .

Există două corecții pentru nucleul Linux care oferă această protecție - PaX și exec-shield . Niciuna dintre acestea nu este încă inclusă în distribuția principală a nucleului. Începând cu versiunea 3.3, OpenBSD a inclus un sistem numit W^X care oferă și controlul timpului de execuție.

Rețineți că această metodă de protecție nu previne corupția stivei. Cu toate acestea, adesea împiedică executarea cu succes a „sarcină utilă” a exploitului. Programul nu va putea insera cod shell în memoria protejată la scriere, cum ar fi segmentele existente de cod executabil. De asemenea, nu va fi posibilă executarea instrucțiunilor pe memoria neexecutabilă, cum ar fi stiva sau heap .

ASLR îngreunează pentru un atacator să determine adresele funcțiilor din codul unui program cu care ar putea efectua un atac cu succes și face atacuri precum ret2libc foarte dificile, deși sunt încă posibile într-un mediu controlat, sau dacă atacatorul este corect ghiceste adresa potrivita.

Unele procesoare , cum ar fi Sparc de la Sun , Efficeon de la Transmeta și cele mai recente procesoare pe 64 de biți de la AMD și Intel, împiedică executarea codului situat în zonele de memorie marcate cu bitul NX special . AMD își numește soluția NX (din engleză  No eXecute ), iar Intel își numește XD (din engleză  eXecute Disabled ). [23]

Protecția spațiului de cod de rulare pentru Windows

Acum există mai multe soluții diferite disponibile pentru protejarea codului executabil pe sistemele Windows , atât de la Microsoft , cât și de la terți.

Microsoft și-a oferit soluția, numită DEP (din engleză.  Data Execution Prevention  - „data execution prevention”), incluzând-o în pachete de service pentru Windows XP și Windows Server 2003 . DEP profită de noile procesoare Intel și AMD care au fost concepute pentru a depăși limita de memorie adresabilă de 4 GB a procesoarelor pe 32 de biți. În aceste scopuri, unele structuri de servicii au fost mărite. Aceste structuri conțin acum bitul NX rezervat. DEP folosește acest bit pentru a preveni atacurile care implică schimbarea adresei unui handler de excepții (așa-numitul exploit SEH ). DEP oferă doar protecție împotriva exploit-ului SEH , nu protejează paginile de memorie cu cod executabil. [9]

În plus, Microsoft a dezvoltat un mecanism de protecție a stivei conceput pentru Windows Server. Stiva este marcată cu ajutorul așa-numiților „informanți” ( English  canary ), a căror integritate este apoi verificată. Dacă „informatorul” a fost schimbat, atunci stiva este coruptă. [24]

Exista si solutii de la terti care impiedica executarea codului situat in zonele de memorie destinate datei sau implementarea mecanismului ASLR.

Utilizarea bibliotecilor securizate

Problema depășirilor de buffer este comună limbajelor de programare C și C++, deoarece acestea nu ascund detaliile reprezentării la nivel scăzut a bufferelor ca containere pentru tipuri de date . Astfel, pentru a evita depășirile de buffer, trebuie menținut un nivel ridicat de control asupra creării și modificării codului care gestionează bufferele. Utilizarea bibliotecilor de tip de date abstracte care efectuează gestionarea automată centralizată a buffer-ului și care includ verificarea depășirii este o abordare inginerească pentru prevenirea depășirii tamponului. [25]

Cele două tipuri principale de date care permit depășirea tamponului în aceste limbi sunt șirurile și matricele . Astfel, utilizarea bibliotecilor pentru șiruri și structuri de date de listă care au fost dezvoltate pentru a preveni și/sau detecta depășirile de buffer evită multe vulnerabilități. Prețul unor astfel de soluții este o scădere a performanței din cauza verificărilor inutile și a altor acțiuni efectuate de codul bibliotecii, deoarece este scris „pentru toate ocaziile”, iar în fiecare caz specific, unele dintre acțiunile pe care le efectuează pot fi redundante.

Istorie

Depășirea tamponului a fost înțeleasă și parțial documentată încă din 1972 în Studiul de planificare a tehnologiei securității computerelor. [26] Cea mai veche utilizare documentată rău intenționată a depășirii tamponului a avut loc în 1988. S-a bazat pe una dintre mai multe exploatări folosite de viermele Morris pentru a se autopropaga pe Internet. Programul a exploatat o vulnerabilitate în serviciul finger Unix . [27] Mai târziu, în 1995, Thomas Lopatik a redescoperit în mod independent depășirea tamponului și a enumerat constatările pe lista Bagtrak . [28] Un an mai târziu, Elias Levy a publicat o introducere pas cu pas despre utilizarea depășirilor de buffer cu stiva, Smashing the Stack for Fun and Profit, în revista Phrack . [12]

De atunci, cel puțin doi viermi de rețea cunoscuți au folosit depășiri de buffer pentru a infecta un număr mare de sisteme. În 2001, viermele Code Red a exploatat această vulnerabilitate în produsul Microsoft Internet Information Services (IIS) 5.0 [29] , iar în 2003 SQL Slammer a infectat mașinile care rulau Microsoft SQL Server 2000 . [treizeci]

În 2003, exploatarea unui buffer overflow prezent în jocurile Xbox licențiate a permis ca software-ul fără licență să ruleze pe consolă fără modificarea hardware folosind așa-numitele modchip -uri . [31] PS2 Independence Exploit a folosit, de asemenea, un buffer overflow pentru a obține același rezultat pentru PlayStation 2 . O exploatare similară pentru Wii Twilight a exploatat această vulnerabilitate în The Legend of Zelda: Twilight Princess .

Vezi și

Note

  1. Erickson, 2010 , 0x320 Buffer Overflow, p. 139.
  2. Wheeler, 2004 , 6. Avoid Buffer Overflow, p. 71.
  3. Erickson, 2010 , 0x321 Stack Buffer Overflow, pag. 142.
  4. Erickson, 2010 , 0x300 Exploits, p. 135-139.
  5. ↑ „HP-UX (PA-RISC 1.1) Overflows” de Zhodiac  . Phrack . Consultat la 8 decembrie 2014. Arhivat din original pe 3 decembrie 2014.
  6. ↑ „The Frame Pointer Overwrite” de klog  . Phrack . Consultat la 8 decembrie 2014. Arhivat din original pe 3 decembrie 2014.
  7. Wheeler, 2004 , 6.1. Pericole în C/C++, p. 71.
  8. Wheeler, 2004 , 6.4. Alte limbi, p. 80.
  9. ↑ 1 2 Data Execution Prevention (DEP  ) . vlaurie.com. Preluat la 8 decembrie 2014. Arhivat din original la 18 decembrie 2008.
  10. Hacking Windows CE  . Phrack . Data accesului: 14 decembrie 2014. Arhivat din original pe 3 decembrie 2014.
  11. DIY Buffer Overflow #2 . revista Xakep. Data accesului: 8 decembrie 2014. Arhivat din original pe 11 decembrie 2014.
  12. ↑ 1 2 „Smashing the Stack for Fun and Profit” de Aleph One  . Phrack . Data accesului: 8 decembrie 2014. Arhivat din original pe 6 februarie 2013.
  13. ↑ CORE-2007-0219: Buffer- ul nucleului de la distanță IPv6 mbufs  al lui OpenBSD . securityfocus.com. Data accesului: 8 decembrie 2014. Arhivat din original la 12 februarie 2012.
  14. Ținte moderne de depășire  . Furtuna de pachete. Consultat la 8 decembrie 2014. Arhivat din original la 23 octombrie 2016.
  15. Baza de date Metasploit Opcode  . Metasploit . Consultat la 15 mai 2007. Arhivat din original pe 12 mai 2007.
  16. Microsoft Technet Security Bulletin MS04-028  (engleză)  (link nu este disponibil) . Microsoft . Preluat la 8 decembrie 2014. Arhivat din original la 4 august 2011.
  17. Scrierea codurilor shell alfanumerice  ia32 . Phrack . Consultat la 14 decembrie 2014. Arhivat din original la 10 martie 2014.
  18. Motorul Shellcode polimorf  . Phrack . Data accesului: 14 decembrie 2014. Arhivat din original pe 11 decembrie 2014.
  19. Exploatările avansate return-into-lib(c)  . Phrack . Data accesului: 14 decembrie 2014. Arhivat din original pe 14 decembrie 2014.
  20. Crearea unui Shellcode arbitrar în șiruri de caractere extinse Unicode  (engleză) (PDF). Ajutor Net Security. Consultat la 8 decembrie 2014. Arhivat din original la 5 ianuarie 2006.
  21. Day, DJ; Sch. de Comput., Univ. din Derby, Derby, Marea Britanie; Zhengxu Zhao; Minhua Ma. Detectarea atacurilor de depășire a tamponului de revenire la libc utilizând sistemele de detectare a intruziunilor în rețea   // IEEE . - 2010. - P. 172-177 . - ISBN 978-1-4244-5805-9 . - doi : 10.1109/ICDS.2010.37 .
  22. Wheeler, 2004 , 6.3. Soluții de compilare în C/C++, p. 79.
  23. Caracteristici  . _ Ubuntu . Preluat la 9 decembrie 2014. Arhivat din original la 8 august 2019.
  24. Perla, Oldani, 2011 , CAPITOLUL 6 Ferestre.
  25. Wheeler, 2004 , 6.2. Soluții de bibliotecă în C/C++, p. 73.
  26. Studiu de planificare a tehnologiei securității computerelor  (engleză) (PDF)  (link nu este disponibil) . Centrul de resurse pentru securitatea computerelor (CSRC). Data accesului: 8 decembrie 2014. Arhivat din original pe 21 iulie 2011.
  27. ^ „A Tour of The Worm” de Donn Seeley, Universitatea din  Utah . world.std.com. Consultat la 3 iunie 2007. Arhivat din original pe 20 mai 2007.
  28. Arhiva listei de corespondență de securitate  Bugtraq . www.security-express.com. Consultat la 3 iunie 2007. Arhivat din original la 1 septembrie 2007.
  29. eEye Digital Security  . eEye Digital Security. Consultat la 3 iunie 2007. Arhivat din original pe 25 iunie 2007.
  30. Microsoft Technet Security Bulletin MS02-039  (engleză)  (link nu este disponibil) . Microsoft . Consultat la 8 decembrie 2014. Arhivat din original pe 7 martie 2008.
  31. Hacker rupe protecția Xbox fără mod-  cip . gamesindustry.biz Consultat la 3 iunie 2007. Arhivat din original pe 27 septembrie 2007.

Literatură

  • James Foster, Mike Price. Protecție împotriva hackurilor: socket-uri, exploit-uri, shellcode = Sockets, Shellcode, Portare și codare. - M . : Editura DMK-press, 2006. - S. 35, 532. - 784 p. - ISBN 5-9706-0019-9 .
  • John Erickson. 0x320 Buffer Overflow // Hacking : Arta exploatării. — ediția a II-a. - Sankt Petersburg. : Simbol-Plus, 2010. - S.  139 . — 512 p. — ISBN 978-5-93286-158-5 .
  • David A. Wheeler. Capitolul 6. Evitați depășirea bufferului // Programare sigură pentru Linux și Unix HOWTO . - 2004. - P. 71. - 188 p.
  • Enrico Perla, Massimiliano Oldani. CAPITOLUL 6 Windows // Un ghid pentru exploatarea kernelului: Atacarea nucleului. - 2011. - P. 334. - 442 str. — ISBN 978-1-59749-486-1 .

Link -uri

Biblioteci și alte protecții