Buffer overflow

A HupWiki-ből...

A buffer overflow (vagy puffer túlcsordulás) akkor következik be, ha egy program saját pointer változója által mutatott bufferében annak méreténél nagyobb mennyiségű adatot próbálnak elhelyezni benne. Ez a legtöbbször biztonsági problémák kapcsán kerül előtérbe.Ez az esemény egyértelműen programozói hibát jelöl.

Tartalomjegyzék

Hogyan következhet be?

Az ilyen hiba az esetek 99%-ában olyan programnyelveket súlyt, amelyek a memóriamenedzsmentet teljes egészében a programozóra bízzák, tehát neki kell gondoskodni a memóriagazálkodásról. (Például C/C++, assembly, stb...) A hiba oka legtöbbször programozói hanyagság vagy nem kellő szakértelem, figyelmetlenség vagy éppen az emberi határokat meghaladó komplexitású kód. Ha a program ellenőrizetlen bemenetet fogad a külvilágból és azt olyan módon tárolja a memóriában, amelyet a programnyelv maga nem ellenőriz, akkor a program máris buffer overflow-veszélyes.

Példa heap buffer overflow sebezhetőségű kódra

 #include <stdio.h>
 int main() {
   char* keresztnev;    /* Ez egy karaktersorozat C-ben*/
 
   malloc(keresztnev, sizeof(char) *20);  /* 20 karakter hosszú helyet foglalunk a memóriában */
   printf("Kerlek ird be a neved: ");
   scanf("%s", keresztnev);               /* Beolvassuk a nevet a keresztnev stringbe */
   printf("Ez a neved: %s", keresztnev);
   free(keresztnev);  
   
   return 0;
 }

Ez azért veszélyes, mert bár 20 karakternyi helyet foglaltunk a keresztnévnek, de ha én azt írom be a programnak, hogy abcdefghijklmnopqrst, akkor sajnos be fogja olvasni és be fogja tenni a 20 karakternyi memóriába, de nem fogja levágni 20 karakternél. Túlírja az eredetileg 20 hosszúnak szánt stringünket és vakon beleír a bufferünkbe. A probléma ott kezdődik, hogy a bufferben a változóknak egymás után van hely foglalva. Tehát ha túlírom a stringet, akkor bizony a programom más változóiba is képes vagyok adatot csempészni. Ezt a hibát ha egy cracker felfedezi, akkor szerkeszthet egy olyan ügyes kis bemeneti adatot, hogy az a rész, ami már túllógna, olyan értéket kapjon, hogy az egy utána lévő változóban érvényes és neki tetsző adatot tartalmazzon. Tehát átveheti a hatalmat a program felett. Gondoljunk csak bele, hogy hol lehet ez problémás:

 #include <stdio.h>
 #incldue <strings.h>
 int main() {
   char* jelszo;    /* Ez egy karaktersorozat C-ben*/
   char  jo_jelszo[] = "pistike123456789qwer";
 
   malloc(jelszo, sizeof(char) *20);  /* 20 karakter hosszú helyet foglalunk a memóriában */
   printf("Kerlek ird be a jelszavad: ");
   scanf("%s", jelszo);               /* Beolvassuk a nevet a keresztnev stringbe */
   if(strcmp(jelszo, jo_jelszo) == 0) {
       printf("Belepes engedelyezve!");
   } else {
       printf("Belepes MEGTAGADVA!");
       free(jelszo);
       return -1;
   }
   free(jelszo);  
 
   return 0;
 }

Ha most egy ilyen programnál én azt adom be a programnak, hogy jelszo123456789qwert*jelszo123456789qwert* akkor máris beenged a program, pedig nem is ez a jelszó, nem is tudtam az igazi jelszót. (A csillag karakter helyére igazából ASCII 0 kódú karaktert kell írni mindkét helyre). Mi történik? Tudom, hogy max 20 karater lehetne a jelszó a program vágyai szerint. Beírom az én kis 20 karakteres jelszavam:jelszo123456789qwert ezt követi egy \0 karakter, ami a C-ben a string-eket kötelezően lezárja. és ezek után túlírom a memóriában is (nemcsak a kódban!!!!) a jelszo stringet követő jo_jelszo stringet az én jelszavamra:jelszo123456789qwert majd lezárom egy \0-lal. És amikor a strcmp() összehasonlítja a bevitt értéket a jó jelszóval, akkor már az általam jónak akart stringet találja ott és beenged.

Példa stack buffer overflow sebezhetőségű kódra

FIXME

Hogyan lehet védekezni?

  • ProPolice, PaX, exec-shield, W^X, stb.
  • figyelmes kódolás
  • A program ellenőrzése Valgrinddel, Splinttel, és más hibakereső eszközökkel
  • automatikus memóriamenedzsmentet használó programnyelv

FIXME: hogyan lehet még buffer overflow? Hogyan lehet ellene védekezni? Ennek kifejtése.