Buferio perpildymo pažeidžiamumas

Turinys

Šioje pamokoje mes kalbėsime apie buferio perpildymą (Buferio perpildymas), ilgai trunkanti klaida, įvyksta, kai duomenys, nukopijuoti į atminties sritį (kuri buvo rezervuota anksčiau), netinkamai tikrinami, gali būti, kad programa veikia tinkamai, jei vartotojas įterpia duomenis su tinkamo dydžio, tačiau jei rezervuosime atmintį 15 simbolių, o vartotojas įterps 20, tai paveiks kitą atminties sritį, kuri gali būti rezervuota arba ne.

Tai gali užkirsti kelią mūsų programai, bet taip pat gali būti daug blogiau, naudotojas, turintis kenkėjiškų ketinimų, gali pasinaudoti šia klaida ir paveikti programos veikimą arba vykdyti savavališką kodą kompiuteryje (paprastai šis kodas atidarys komandų vertėją) ). Be to, jei programa veikia su padidintomis privilegijomis, turime rimtų saugumo trūkumų. Kitas išpuolis, galintis pakeisti programos veikimą arba įvesti kodą, yra XSS.

PastabaVykdymai, kuriuos matysite šioje pamokoje, buvo atlikti 32 bitų „Ubuntu 16.04“ operacinėje sistemoje.

Pažiūrėkime a Paprastas C kodo, kuris yra pažeidžiamas šios atakos, pavyzdys, paleisdami programą, turime perduoti parametrą - programą tikėtis gauti ne ilgesnę kaip 15 simbolių eilutę, jei tai laukiama eilutė, tai bus sėkminga prieiga, jei ne, ji bus „uždrausta“. Kodas yra toks, kaip parodyta žemiau:

 #include #include #define password "Test" void test (char * str) {char buffer [15]; int n = 0; strcpy (buferis, str); if (strcmp (buferis, slaptažodis) == 0) {n = 1; } if (n) {printf ("Sėkmė \ n"); išėjimas (0); } else {printf ("Prieiga uždrausta \ n"); }} int main (int argc, char * argv []) {if (argc <2) {printf ("Programai reikalingas parametras \ n"); išėjimas (-1); } testas (argv [1]); }
Programa pavadinta perpildymas.c, o kompiliavimui buvo naudojama:
 gcc overflow.c -o perpildymas -fno -stack -protector
Paskutinė dalis: -fno-stack-protector Jis naudojamas tam, kad kompiliatorius neapsaugotų ir galėtume parodyti pavyzdį. Jei vartotojas įveda teisingus duomenis, kurie yra ne daugiau kaip 15 simbolių eilutė, programa veikia gerai, jei įvedame neteisingą „slaptažodį“, jis mums parodys Prieiga uždraustair jei įdėsime "Bandymas„Išleis mus Sėkmė. Pažiūrėkime, kaip užfiksuoti programą, vykdančią 2 kartus, vieną kartą su neteisinga prieiga, o kitą - su teisinga eilute:

Matome, kad viskas veikia teisingai. Bet ką daryti, jei įterpiame viršutinę eilutę, pažiūrėkime, kas atsitiks:

Mes pradėjome programą su 20 raidžių Air parodo mums Sėkmė. Šioje programoje mes nieko neturime, mes tiesiog išeiname iš programos, tačiau patekome į ribotą zoną nežinodami slaptažodžio. Jei pakeisime šią funkciją:

 strcpy (buferis, str);
Taip:
 strncpy (buferis, str, 15);
Y kodą vykdome 20 raidžių A, turime tokią išvestį:

Taip pat galite pamatyti, kad mes tuo pasinaudojame strcmp, vietoj to turėtume naudoti strncmp, todėl mes taip pat kontroliuojame dydį. Mes kontroliavome, kad galima nukopijuoti ne daugiau kaip 15 simbolių, todėl tai neturi įtakos mūsų programai, jei jie įterpiami daugiau. Jei po pranešimo rodymo Sėkmė vykdome sistemos komandą (šiuo atveju kas aš esu), mes gauname informaciją:

Aukščiau mes nesame root, bet jei vykdome jį naudodami sudo, gauname:

Vienintelis dalykas, kurį pridėjome, yra kodo eilutė, kurią matėme aukščiau, po kodo eilute:

 printf („Sėkmė \ n“);
Mes įdėjome:
 sistema („whoami“);
Norėdami šiek tiek suprasti, kas nutiko, aš pakeisiu programą, kad būtų parodyti 2 mūsų turimi kintamieji (buferis Y n) ar tai teisinga, ar ne, o žemiau yra išvestis, pirmiausia įterpiame eilutę, kuri bus laikoma teisinga ("Bandymas“), Tada neteisingas, neviršijantis ilgio ir galiausiai 20 raidžių A.:

Matome, kad per pirmąjį įvykdymą tai verta 1 Kintamasis n, nes perduota grandinė yra teisinga, antroje - verta 0, nes tai neteisinga, bet paskutinėje - verta 1094795585, todėl praleidžiama sąlyga, kurią mes nustatėme jei (n), tai bus tiesa, kol n skirsis nuo 0. Tai nėra gera būklė, nors ji neturėtų žlugti, jei likusi kodo dalis būtų teisinga. Jei įdėsime 16 raidžių A. kaip parametrą matysime, kad kintamojo reikšmė n tai yra 65:

Jei pažvelgsime į ASCII kodą, skaičius 65 atitinka laišką Įmatėme, kad mes netyčia palietėme kintamojo n atmintį, kad papildoma raidė, kurią perdavėme kaip parametrą, pateko į kintamąjį n. Mes turėtume tokią atmintį:

Jei peržengsime simbolių ribas, gali būti, kad jis siunčia mums pranešimą apie segmento pažeidimą (jei pašalinsime išeiti (0) ką mes turime jei (n)), tai matome šiame paveikslėlyje:

Šis įspėjimas atsirado dėl bandymo patekti į atminties sritį, kuri yra už tos ribos, kurią operacinė sistema priskyrė programai. Jei sudarytume pavyzdį taip:

 gcc overflow.c -o perpildymas -fstack -protector
Arba tiesiog pašalinti -fno-stack-protector Iš kompiliacijos, kurią matėme pirmą kartą, ir vykdome kodą perpildydami, gauname tokį rezultatą:

Papildoma apsauga, kurią mums suteikia gcc.

PastabaJei norime įvykdyti kodą (apvalkalo kodas) grąžinimo adresą turėtume perrašyti savo apvalkalo kodu, jis yra šiek tiek sudėtingesnis nei pavyzdyje pateiktas pavyzdys, todėl reikalauja daugiau darbo.

Jei kam nors pavyks pasinaudoti šiuo pažeidžiamumu, tai gali padaryti jums daug žalos. Venkite tokio tipo gedimų ir tai, kad kenkėjiškas vartotojas gali tuo pasinaudoti, yra labai paprasta, teisingai programuoti, turite gerai žinoti naudojamą programavimo kalbą, žinoti, kokias funkcijas naudoti ir kokių nenaudoti, išbandyti programą Na, ne tik turint teisingus duomenis, jis taip pat turi tinkamai veikti, kai susiduriame su nenumatytais duomenimis.

Kitos atakos, kurias galite peržiūrėti ir žinoti, kad jos jūsų nepaveiktų ir nesumažintų jų rizikos: DoS ir Brute Force. Nepamirškite patikrinti CVE puslapyje, ar nėra pažeidžiamumų.

Ar jums patiko ir padėjo ši pamoka?Galite apdovanoti autorių paspausdami šį mygtuką, kad suteiktumėte jam teigiamą tašką

Padėsite svetainės plėtrą, dalintis puslapį su draugais

wave wave wave wave wave