O privire asupra exploatării vulnerabilităților

În timp ce așteptam cu nerăbdare să discut în continuare despre acest subiect, permiteți-mi să vă povestesc un pic de istorie, teorie și practică privind vulnerabilitățile. Cu toții am auzit până acum că defectele de securitate pot costa mult, știm cu toții că trebuie să ne menținem software-ul la zi, știm cu toții că multe actualizări sunt cauzate de erori de securitate. Dar astăzi vă voi spune puțin despre modul în care aceste erori sunt găsite și exploatate 🙂 Dar înainte de aceasta vom clarifica câteva detalii pentru a avea o imagine de ansamblu mai bună.

Înainte de a începe

Mai întâi vreau să vă spun că ne vom concentra pe prima vulnerabilitate pe care am învățat să o exploatez, cunoscuta Deborduri tampon, în această vulnerabilitate profităm de lipsa verificării memoriei pentru a face lucruri distractive 🙂 Dar hai să clarificăm puțin mai multe despre aceasta.

Acesta nu va fi un scenariu real

Nu-mi permit să-i învăț să rupă orice program pe care-l văd - mai întâi pentru că este periculos pentru computerele lor, în al doilea rând pentru că ar dura mai mult decât cota mea obișnuită de cuvinte.

Plecăm într-o excursie în anii '80

Ceea ce vă voi arăta că pot face pe laptopul meu, dar nu înseamnă că se poate face astăzi într-un mod simplu 🙂 multe dintre aceste concepte au fost deja exploatate de atâtea ori încât au apărut noi metode de protecție și noi metode de a le sustrage 😛 dar asta ne întoarce în același loc, nu există spațiu pentru a putea spune toate acestea 🙂

Este posibil să nu funcționeze pe procesorul dvs.

Deși voi folosi un exemplu foarte simplu, vreau să fie destul de clar de la început că detaliile acestui lucru sunt atât de multe și atât de variate încât la fel cum poate ieși la fel ca mine, dacă doriți să îl încercați, este posibil ca efectul dorit să nu fie atins. 🙂 Dar vă puteți imagina că nu pot explica asta în acest spațiu, mai ales că, cu această introducere, am luat deja peste 300 de cuvinte, așa că ajungem direct la punctul nostru.

Ce este un Depășire tampon

Pentru a răspunde la acest lucru, trebuie mai întâi să înțelegem prima jumătate a acestei combinații.

Tampoanele

Deoarece totul este despre memorie într-un computer, este logic să existe un anumit tip de container de informații. Când vorbim despre intrări iesiri, ajungem direct la conceptul de tampoane. Pentru a fi scurt, a tampon Este un spațiu de memorie de dimensiuni definite în care vom stoca o cantitate de informații, simplă 🙂

Depășirile apar, așa cum sugerează și numele, atunci când un tampon se umple cu mai multe informații decât poate gestiona. Dar de ce este acest lucru important?

Stivui

Cunoscute și sub denumirea de stive, sunt un tip de date abstract în care putem grămadă informație, principala lor caracteristică este că au o ordonare LIFO (Ultimul intrat, primul ieşit). Să ne gândim o secundă la un teanc de plăci, le punem deasupra una câte una, apoi le scoatem una câte una din partea de sus, asta face ca ultima placă pe care am pus-o (cea care este în partea de sus) să fie prima placă pe care o vom scoate, evident dacă putem scoate o singură farfurie la un moment dat și decidem să o facem în această ordine: P.

Acum, că știți aceste două concepte, trebuie să le punem în ordine. Stivele sunt importante, deoarece fiecare program pe care îl rulăm are al său stivă de execuție. Dar această stivă are un caracteristică specialăcrește în jos. Singurul lucru pe care trebuie să-l știți este că, în timp ce rulează un program, când se apelează o funcție, stiva trece de la un număr X din memorie la un număr (Xn). Dar, pentru a continua, trebuie să înțelegem încă un concept.

Indicatori

Acesta este un concept care îi înnebunește pe mulți programatori atunci când încep în lumea C, de fapt marea putere a programării C se datorează în parte utilizării indicatorilor. Pentru a simplifica, un indicator indică o adresă de memorie. Sună complex, dar nu este complex, cu toții avem RAM în mașinile noastre, nu? Ei bine, acest lucru poate fi definit ca un dispunerea consecutivă a blocurilor, aceste locații sunt de obicei exprimate în numere hexazecimale (de la 0 la 9 și apoi de la A la F, cum ar fi 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Aici ca o notă curioasă, 0x10 NU este egal cu 10 😛 dacă îl convertim în ordine zecimală ar fi același lucru cu a spune 15. Acesta este ceva care, de asemenea, încurcă mai mult de unul la început, dar să trecem la el.

Înregistrări

Procesoarele lucrează cu un număr de înregistrări, care funcționează pentru a transmite locații de la memoria fizică la procesor, pentru arhitecturi care utilizează 64 de biți, numărul de registre este mare și dificil de descris aici, dar pentru a obține ideea, registrele sunt ca niște indicatori, indică printre altele lucruri, un spațiu de memorie (locație).

Acum practică

Știu că a fost o mulțime de informații de procesat până acum, dar în realitate sunt probleme oarecum complexe pe care încerc să le explic într-un mod foarte simplu, vom vedea un mic program care utilizează tampoane și îl vom rupe pentru a înțelege acest lucru despre revărsări, evident că acesta nu este Este un program real și vom „sustrage” multe dintre contramăsurile care sunt folosite astăzi, doar pentru a arăta cum se făceau lucrurile înainte 🙂 și pentru că unele dintre aceste principii sunt necesare pentru a putea învăța lucruri mai complexe 😉

GDB

Un program grozav care este, fără îndoială, unul dintre cele mai utilizate de programatorii C. Printre numeroasele sale virtuți avem faptul că ne permite să vedem toate acestea despre care am vorbit până acum, registre, stivă, tampoane etc. 🙂 Să vedem programul pe care îl vom folosi pentru exemplul nostru.

retinput.c

Proprie. Christopher Diaz Riveros

Acesta este un program destul de simplu, vom folosi biblioteca stdio.h pentru a putea obține informații și a le afișa într-un terminal. Putem vedea o funcție numită return_input care generează o tampon denumit mulțime, care are o lungime de 30 bytes (tipul de date char are o lungime de 1 octet).

Funcția gets(array); solicitați informații de consolă și funcție printf() returnează conținutul matricei și îl afișează pe ecran.

Fiecare program scris în C începe cu funcția main(), acesta va fi însărcinat doar cu apelarea return_input, acum vom compila programul.

Proprie. Christopher Diaz Riveros

Să luăm puțin din ceea ce tocmai am făcut. Optiunea -ggdb îi spune lui gcc să compileze programul cu informații pentru ca gdb să poată depana corect. -fno-stack-protector Este o opțiune pe care, evident, nu ar trebui să o folosim, dar pe care o vom folosi pentru că altfel ar fi posibil să generăm depășirea bufferului în stivă. În cele din urmă am testat rezultatul. ./a.out pur și simplu rulează ceea ce tocmai am compilat, cere informații și le returnează. Alergare 🙂

avertismente

O altă notă aici. Puteți vedea avertismentele? clar este ceva de luat în calcul atunci când lucrăm cu cod sau compilăm, acest lucru este puțin evident și există puține programe care astăzi au funcția gets() În cod. Un avantaj al Gentoo este că, prin compilarea fiecărui program, văd ce ar putea fi greșit, un program „ideal” nu ar trebui să le aibă, dar ați fi surprins de câte programe mari au aceste avertismente, deoarece sunt doar FOARTE mari și este greu să le urmăriți. funcții periculoase atunci când există multe avertismente în același timp. Acum, dacă continuăm

Depanarea programului

Proprie. Christopher Diaz Riveros

Acum această parte poate fi un pic confuză, dar din moment ce am scris deja suficient, nu-mi permit să explic totul, așa că îmi pare rău dacă vedeți că merg prea repede 🙂

Dezarmarea codului

Să începem prin a ne uita la programul nostru de limbaj computerizat.

Proprie. Christopher Diaz Riveros

Acesta este codul funcției noastre principale din Asamblare, asta înțelege procesorul nostru, linia din stânga este adresa fizică din memorie, <+ n> este cunoscut ca compensa, practic distanța de la începutul funcției (principal) la acea afirmație (cunoscută sub numele de opcode). Apoi vedem tipul de instrucțiune (push / mov / callq ...) și unul sau mai multe registre. Rezumat putem spune că este indicația urmată de sursă / origine și destinație. <return_input> se referă la a doua noastră funcție, să aruncăm o privire.

return_input

Proprie. Christopher Diaz Riveros

Acest lucru este puțin mai complex, dar vreau doar să verificați câteva lucruri, există o etichetă numită <gets@plt> și un ultim opcode numit retq indicând sfârșitul funcției. Vom pune câteva puncte de întrerupere, unul în funcție gets și altul în retq.

Proprie. Christopher Diaz Riveros

Alerga

Acum vom rula programul pentru a vedea cum începe acțiunea.

Proprie. Christopher Diaz Riveros

Putem vedea că apare o mică săgeată care indică opcode-ul unde ne aflăm, vreau să țină cont de direcția 0x000055555555469b, aceasta este adresa după apelul către return_input în funcțiune main , acest lucru este important, deoarece acesta este locul în care programul ar trebui să revină când ați terminat de primit intrare, hai să intrăm în funcție. Acum vom verifica memoria înainte de a intra în funcție gets.

Proprie. Christopher Diaz Riveros

Am pus înapoi funcția principală pentru dvs. și am evidențiat codul la care mă refeream, după cum puteți vedea, din cauza endianness a fost separat în două segmente, vreau să țină cont de direcția 0x7fffffffdbf0 (primul din stânga după comandă x/20x $rsp) deoarece aceasta este locația pe care trebuie să o folosim pentru a verifica rezultatul obținut, să continuăm:

Ruperea programului

Proprie. Christopher Diaz Riveros

Le-am evidențiat pe acestea 0x44444444deoarece sunt reprezentarea D-urilor noastre 🙂 acum am început să adăugăm intrare la program și, după cum puteți vedea, suntem doar două linii de la adresa dorită, o vom completa până când suntem chiar înainte de adresele pe care le-am evidențiat în pasul anterior.

Schimbarea căii de întoarcere

Acum, că am reușit să introducem această secțiune a codului unde indică revenirea funcției, să vedem ce se întâmplă dacă schimbăm adresa 🙂 în loc să mergem la locația codului opțional care o urmează pe cea pe care o aveam acum un moment, ce crezi dacă ne întoarcem la return_input? Dar pentru aceasta, este necesar să scriem adresa pe care o dorim în binar, o vom face cu funcția printf din bash 🙂

Proprie. Christopher Diaz Riveros

Acum am primit informațiile de două ori, cu siguranță programul nu a fost creat pentru asta, dar am reușit să spargem codul și să-l facem să repete ceva ce nu trebuia să facă.

reflecții

Această schimbare simplă poate fi considerată o exploata foarte de bază 🙂 a reușit să rupă programul și să facă ceva ce vrem să facă el.

Acesta este doar primul pas într-o listă aproape infinită de lucruri de văzut și de adăugat, există modalități de a adăuga mai multe lucruri decât simpla repetare a unei comenzi, dar de data aceasta am scris multe și tot ce ține de codificare shell Este un subiect să scrii mai mult decât articole, cărți complete aș spune. Îmi pare rău dacă nu am reușit să aprofundez puțin mai mult subiecte pe care mi le-aș fi dorit, dar cu siguranță va exista o șansă 🙂 Salutări și mulțumiri pentru că am ajuns aici.


Conținutul articolului respectă principiile noastre de etică editorială. Pentru a raporta o eroare, faceți clic pe aici.

14 comentarii, lasă-le pe ale tale

Lasă comentariul tău

Adresa ta de email nu va fi publicată.

*

*

  1. Responsabil pentru date: Miguel Ángel Gatón
  2. Scopul datelor: Control SPAM, gestionarea comentariilor.
  3. Legitimare: consimțământul dvs.
  4. Comunicarea datelor: datele nu vor fi comunicate terților decât prin obligație legală.
  5. Stocarea datelor: bază de date găzduită de Occentus Networks (UE)
  6. Drepturi: în orice moment vă puteți limita, recupera și șterge informațiile.

  1.   2p2 el a spus

    Fii mai direct. Scrie mai puțin și concentrează-te asupra a ceea ce contează

    1.    ChrisADR el a spus

      Bună, mulțumesc pentru comentariu.

      Ca să spun adevărul, am tăiat o mare parte din idei, dar chiar și așa mi s-a părut că am lăsat minimul pentru ca cineva care nu are cunoștințe de programare să-și poată face o idee.

      În ceea ce priveşte

      1.    anonim el a spus

        Problema este că cei care nu au cunoștințe de programare nu vor afla nimic pentru că este prea complex pentru a începe, dar cei care știu să programeze apreciază că sunt mai direcți.

        Cred că nu poți ajunge la toată lumea, trebuie să alegi și, în acest caz, ai păcătuit să vrei să acoperi mult.

        Apropo, vă spun ca o critică constructivă, îmi plac aceste subiecte și aș vrea să continuați să scrieți articole, felicitări!

    2.    anonim el a spus

      Cred că același lucru.

      1.    ChrisADR el a spus

        Mulțumesc mult amândurora !! Este cu siguranță dificil să înțelegem cum să ajungem la publicul țintă atunci când adevărul este că numărul persoanelor cu un nivel avansat de programare care citesc aceste articole este redus (cel puțin acest lucru poate fi dedus pe baza comentariilor)

        Cu siguranță am păcătuit din dorința de a simplifica ceva care necesită o bază largă de cunoștințe pentru a fi înțeleasă. Sper să înțelegeți că, de când abia încep la blog, nu am descoperit încă punctul exact în care cititorii mei știu și înțeleg ce spun. Asta ar face mult mai ușor să spui adevărul 🙂

        Voi încerca să fiu mai scurt atunci când merită fără a depersonaliza formatul, deoarece separarea modului de scriere de conținut este puțin mai complicată decât s-ar putea imagina, cel puțin le am destul de legate, dar presupun că în cele din urmă voi putea adăuga linii în în loc să taie conținut.

        În ceea ce priveşte

  2.   Mario el a spus

    Unde ai putea afla mai multe despre subiect? Orice carte recomandată?

    1.    ChrisADR el a spus

      Exemplul a fost preluat din The Shellcoder's Handbook de Chris Anley, John Heasman, Felix Linder și Gerardo Richarte, dar pentru a face traducerea pe 64 de biți a trebuit să aflu despre arhitectura mea, manualul dezvoltatorului intel, volumele 2 și 3 sunt un sursă destul de fiabilă pentru asta. De asemenea, este bine să citiți documentația GDB, care vine împreună cu comanda „info gdb”, Pentru a învăța Asamblare și C există multe cărți foarte bune, cu excepția faptului că cărțile Asamblării sunt cam vechi, deci există un spațiu de completat documentație.

      Shellcode-ul în sine nu mai este la fel de eficient în aceste zile din diverse motive, dar este totuși interesant să înveți noi tehnici.

      Sper că te va ajuta puțin 🙂 Salutări

  3.   Franz el a spus

    Bun articol, vechiul blog desdelinux a renăscut =)
    Când spuneți că shell-ul la distanță nu este atât de eficient, vă referiți la măsuri contrare concepute pentru a atenua atacurile, acestea îl numesc securitate ofensatoare.
    Salutări și continuă

    1.    ChrisADR el a spus

      Mulțumesc Franz words cuvinte foarte amabile, de fapt am vrut să spun că Shellcoding astăzi este mult mai complex decât ceea ce vedem aici. Avem ASLR (generator de locație de memorie aleatorie) protectorul stivei, diferitele măsuri și contramăsuri care limitează numărul de coduri de opțiuni care pot fi injectate într-un program și este doar începutul.

      Salutari,

  4.   Software-ul gratuit el a spus

    Bună ziua, veți face o altă parte extinzând subiectul? E interesant

    1.    ChrisADR el a spus

      Bună ziua, subiectul este cu siguranță destul de interesant, dar nivelul de complexitate pe care l-am lua ar deveni foarte ridicat, implicând probabil un număr mare de postări pentru a explica diferitele premise pentru a-l înțelege pe celălalt. Probabil voi scrie despre asta, dar nu vor fi următoarele postări, vreau să scriu câteva subiecte înainte de a continua cu asta.

      Salutări și mulțumiri pentru distribuire

  5.   cactus el a spus

    Foarte bine che! Contribuiți la postări grozave! O întrebare: încep chestia de securitate IT citind o carte numită „Asigurarea securității prin testarea stiloului”. Este recomandată această carte? Cum sugerați să încep să mă interesez despre aceste probleme?

    1.    ChrisADR el a spus

      Bună ziua, cactus, este un univers întreg despre vulnerabilități, și altele, ca să spun adevărul, depinde foarte mult de ceea ce vă atrage atenția și de nevoile pe care le aveți, un manager IT nu trebuie să știe la fel ca un pen-tester, Sau un cercetător al vulnerabilității sau un analist criminalist, o echipă de recuperare în caz de dezastru are un set de abilități foarte diferite. Evident, fiecare dintre ele necesită un nivel diferit de cunoștințe tehnice, vă recomand să începeți să descoperiți exact ceea ce vă place și să începeți să devorați cărți, articole și altele și, cel mai important, să practicați tot ce citiți, chiar dacă este depășit , asta va face diferența în cele din urmă.
      Salutari,

  6.   Eizen el a spus

    Buna ziua.
    Vă mulțumesc foarte mult pentru că ați explicat acest subiect, precum și pentru că ați comentat că pentru informații suplimentare avem „The Shellcoder's Handbook”. Am deja o lectură în așteptare 😉

bool (adevărat)