Puhvri ületäitumise rünnakud ja vastumeetmed

From EIK wiki

Autor

Heidi Olesk AK31

Sissejuhatus

Puhvri ületäitumist (Buffer Overflow) peetakse üheks Interneti tõsisemaks rünnakuliigiks. Rünnates puhvrit on häkkeril võimalik kasutaja andmeid varastada ja kogu arvuti üle kontroll saavutada [1]. Kräkkerid kasutavad taolist moodust arvuti viirusega nakatamiseks. Lühidalt öeldes tekib puhvri ületäitumine olukorras, kus pahalane saadab liiga palju andmeid puhvrisse ja programm ei ole suuteline kontrollima puhvri seisundit ehk tegemist on programmeerimise veaga. Seetõttu peaksid rakendusprogrammidel olema fikseeritud suurusega puhvrid andmete hoidmiseks ja mitte ainult, aga sellest juba täpsemalt allpool.

Pilku ajalukku heites tuleb ära märkida esimene teadaolev puhvri rünnaku juhtum, kui 1988 aastal USA-s tudeng Morrise poolt tekitatud Internetiuss põhjustas suure osa arvutivõrkude kokkukukkumise, kus kasutati puhvri ületäitumise turvaauku ja Robert Morrisest sai esimene virtuaalkurjategija.[2]
Kui minimaalne võib olla puvhri ületäitumine, et seda saaks turvaauguna ära kasutada? On teada juhtum, kus tegemist oli vaid ühe-baidise ületäitumisega, mida pahalane kurjasti kasutas kurjasti ära.

Põhimõisted

Puhver mäluosa ajutiseks infosalvestuseks. Näiteks brauser kasutab veebilehekülgede ja nende osade (piltide) ajutiseks hoidmiseks.[3]

Pinu (stack) on andmestruktuur, millest kõigepealt võetakse viimati salvestatud andmeelement. Piltlik võrdlus mündihoidjaga, mille põhjas on vedru ning millesse saab münte lisada vaid pealtpoolt ja et pealt münt kätte saada, tuleb kõigepealt välja võtta pealmine st viimati lisatud münt. [4]

big-endian - jämedaotsaline baitide järjekord andmestringis, kus kõige suurema kaaluga bait on salvestatud kõige esimesena ja selle aadressnumber on kõige väiksem ehk arvu hakatakse lugema kõige „jämedamast“ baidist. [5]

Puhvri ületäitumise tekkepõhjused

Arvutiturbes ja programmeerimises on puhvri ületäitumine või puhvri ülejooksmine anomaalia, kus protsess salvestab andmed puhvrisse väljapool seda mälu, mida programmeerija pole tegelikult ette näinud. Lisaandmed kirjutavad üle lähedal oleva mälu, mis võivad osutuda puhvriteks, konstantideks, lippudeks või muutujateks. See võib omakorda põhjustada ebanormaalseid programmi käitumist sisaldades mälu pöördumiste vigu, vääraid tulemusi, programmi töö lõpetamist või turvasüsteemist läbimurdmist. Põhiliselt juhtub puhvri ületäitumine char stringide puhul ühest puhvrist teise kopeerimisel. Paljud masinkäsud edastavad andmeid senikaua kuni saabub andmestringi lõppu tähistav NULL. Selline käsk on potentsiaalselt ohtlik, aga seda on võimalik vältida kasutades käske, mis loevad või edastavad kindla arvu baite.

Puhvri ületäitumised võivad olla põhjustatud nendest sisenditest, mis on disainitud koodi täitma. Taolisi tegevusi peetakse põhilisteks tarkvara nõrkusteks, mida võidakse pahatahtlikult ära kasutada. Piiride kontrollimine võib ära hoida puhvri ületäitumise. Programmeerimiskeeltest seostatakse puhvri ületäitumisega just selliseid vaba süntaksiga keeli nagu C ja C++ , kuhu ei ole sisse ehitatud andmete ülekirjutamise või pöördumiste vastast kaitset ükskõik millistele mälu osadele. Sageli tekib taoline olukord, kui programmeerija ei ole viitsinud kontrollida, kas andmed reaalselt puhvrisse mahuvad. Pinus asuvate puhvrite puhul soditakse ära pinu ja muudetakse tagasipöördumisaadress.
Peale pinu võib ka muid mälualasid rünnata. Näiteks kirjutatakse teised muutujad üle.

Selgitavad näited

Järgmises näites on programmis defineeritud 2 andmeühikut, mis on mälus kõrvuti. 8-baidine stringi puhver A ja 2-baidine integer väli B. Algselt ei sisalda A midagi ja B sisaldab numbrit 1979. Characterid on 1 bait laiad

variable name A B
value [null string] 1979
hex value 00 00 00 00 00 00 00 00 07 BB

Kui programm üritab salvestada null-lõpetatud stringi „excessive“ puhvrisse A, siis ebaõnnestunud stringi pikkuse kontrollimine viib selleni, et B väärtus kirjutatakse üle, sest A väljale oli 1 baidi võrra rohkem mälu vaja kui algselt planeeritud oli.

variable name A B
value 'e' 'x' 'c' 'e' 's' 's' 'i' 'v' 25856
hex 65 78 63 65 73 73 69 76 65 00

Ehkki programmeerija ei ole kavatsenud üldse B väärtust välja vahetada, on B väärtus nüüd asendatud numbritega, millele on kuju andnud char stringi viimane osa. Selles näites on väärtus toodud big-endian (vt mõiste selgitust ülal) süsteemis, mis kasutab ASCII-d, „e“-le järgneb null byte-i, mis muutub numbriks 25856. Kui B oli ainuke väärtustatud muutuja, mis programmi poolt oli defineeritud, siis kirjutades veel pikema stringi, mis läks B lõppu, võib tekkida selline error nagu segmenteerimise viga ja seejärel protsess lõpetatakse. [6]

Ohtlike funktsioonide näited:

strcpy(char *dest, const char *src)
dest ületäitumine

! strncpy
strcat(char *dest, const char *src)
dest ületäitumine

! strncat
getwd(char *buf)
buf ületäitumine

! getcwd
gets(char *s)
s ületäitumine

! fgets
[vf]scanf(const char *format, ...)
argumentide ületäitumine

! argumentide max pikkused mustrisse
[v]sprintf(char *str,
const char *format, ...)
str ületäitumine
! [v]snprintf

Muid ohtlikke konstruktsioone:
system(string);
popen(string);
printf(str) või printf("%s", str); ?
Viimane printf on formaadistringi rünnak: %n käsib printf-l kirjutada muutujasse seni kuni väljastatakse kästud sümbolite arvu.

Kaitse ja vastumeetmed

Tuleks kontrollida kõikide puhvrite pikkusi ja ei tohiks kasutada ebaturvalisi funktsioone, mis lasevad üle puhvri otsa kirjutada. Kasutada taolisi tehnikaid mälu kaitseks, mis keelavad ühel programmil juhuslikult teise programmi töösse vahele segamise. Mitmesuguseid võtteid kasutades luuakse mälus programmi ümber kaitsepiir ning programmis sisalduvatel käskudel keelatakse viidata andmetele väljaspool seda piiri. Kui programm läheb siiski oma piiridest välja, siis DOS, Windows 3.x, Windows 95, Windows 98 ja teised vanemad personaalarvutite opsüsteemid lihtsalt lukustuvad (lock up, crash, bomb, abend jne). Sellised opsüsteemid nagu UNIX, OS/2, Windows NT, Windows 2000 ja Windows XP on vastupidavamad ja enamasti sulgevad valesammu teinud programmi ilma, et see mõjutaks ülejäänud progammide tööd.
Pinusse saab lisada kontrollväärtuse kas randomiseerimise või nullbaidi sisaldavuse teel. Veel saaks tekitada teegid pinuviidaga arvestavate variantidega ohtlikest funktsioonidest (libsafe, libverify ...) Märkima peab siiski, et ükski neist hädavahenditest ei anna täielikku kaitset.

Soovitus: Memory Firewall Comodo Groupilt, mis pakub laiaulatuslikke turvalahendusi arvutitele. Comodo Memory Firewall on väike, aga tõhus programm, mis nii ennetab kui ka kaitseb puhvri ületäitumise probleemi. Sisaldub Comodo Internet Security paketis, kuid kes kasutavad teiste tootjate turvalahendusi, võivad Comodo Memory Firewalli arvutile täiendavaks kaitseks tirida. Comodo firma ei ole ainult omakasu peal väljas st praktiliselt iga tasulise versiooni kõrval pakutakse ka tasuta versiooni. Proovi siit: Media:http://personalfirewall.comodo.com/

Kasutatud kirjandus:

[1] http://www.arvutiturve.wordpress.com/2009/11/01/puhvri-uletaitumine-buffer-overflow/
[2] http://et.wikipedia.org/wiki/Robert_Tappan_Morris
[3] http://www.vallaste.ee/index.htm?Type=UserId&otsing=2864
[4] http://www.vallaste.ee/index.htm?Type=UserId&otsing=2864 http://math.ut.ee/~mroos/turve/2001/prog_c_4.pdf
[5] http://vallaste.ee/index.htm?Type=UserId&otsing=6573
[6] http://en.wikipedia.org/wiki/Buffer_overflow