Așa-numitele „injecții SQL” sunt un tip de atac asupra unei aplicații care exploatează defectele de securitate din baza de date. În această lecție, vom vedea exemple de injecții SQL. Această lecție se bazează pe articolul lui Steve Friedl SQL Injection Attacks by Example pe care vă recomand să îl citiți sau pe foaia de trucuri cu injecție SQL. Desigur, obiectivul acestei lecții este de a crește gradul de conștientizare a necesității de a proteja orice aplicație web de acest tip de atac.

Exemplu de aplicație

Vom folosi ca exemplu o aplicație similară cu cea din exercițiile Baze de date 1.

  • Această aplicație are un meniu cu trei opțiuni:
    • Ștergeți totul, pentru a șterge și a crea tabelul utilizatorului, care conține doar două câmpuri (numele și parola utilizatorului).
    • Adăugați utilizatori, pentru a adăuga nume de utilizatori și parolele acestora în tabelul utilizatorilor.
    • Intrați în sistem, care simulează o pagină de autentificare într-o aplicație web, solicitând un nume de utilizator și o parolă, verificând dacă este în tabelul utilizatorilor și răspunde
      • numele de utilizator și parola sunt corecte.
      • numele de utilizator este corect, dar parola nu este corectă.
      • numele de utilizator nu este corect.
  • Această aplicație este vulnerabilă la unele atacuri de injecție SQL deoarece datele trimise de utilizator sunt incluse în interogările către baza de date fără niciun tratament anterior.
  • Această aplicație nu este vulnerabilă la toate atacurile de injecție SQL discutate în această lecție, deoarece folosește extensia PDO. Dacă doriți să testați o aplicație similară vulnerabilă la toate atacurile discutate în această lecție pe computer, puteți descărca acest fișier (injection_sql_2.zip) și testați-l pe computerul dvs.

SQL Injection 1 - Accesați aplicația fără a avea un nume de utilizator sau o parolă

Când utilizatorul tastează un nume de utilizator și o parolă, aplicația răspunde la unul dintre cele trei mesaje:

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Corectați numele de utilizator și parola.

Nume de utilizator incorect.

Pentru a verifica dacă aplicația include datele trimise de utilizator fără niciun tratament anterior, putem trimite o ofertă (simplă sau dublă) ca date.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Nume de utilizator incorect.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Eroare de interogare.

Acest ultim mesaj („Eroare la interogare”) ne anunță că datele nu sunt procesate și că interogările sunt, de asemenea, delimitate prin ghilimele duble. De ce?

Probabil că codul aplicației dvs. arată cam așa:

Punând un ghilimel dublu la începutul numelui de utilizator, interogarea devine

Această interogare este corectă (nu conține erori de sintaxă) și atunci când rulați baza de date returnează doar 0.

Cu toate acestea, introducerea unei singure citate la începutul numelui de utilizator transformă interogarea în

Această interogare nu este corectă (conține o eroare de sintaxă din cauza ghilimelelor din ghilimele celei de-a doua linii și când este executată, baza de date dă o eroare.

Acum, că știm că interogarea este delimitată de ghilimele duble, putem scrie câteva date care vor modifica interogarea și vor face aplicația să creadă că am introdus date de la un utilizator înregistrat.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Corectați numele de utilizator și parola.

În acest caz, interogarea bazei de date va fi ceva de genul acesta:

Această interogare este corectă și, atunci când este rulată, baza de date returnează numărul total de înregistrări din tabel, deoarece condiția este întotdeauna îndeplinită, chiar dacă numele de utilizator și parola sunt incorecte, deoarece condiția finală SAU '1' = '1 'este întotdeauna adevărat.

SQL Injection 2 - Aflați numele câmpurilor

Numele câmpurilor pot fi găsite prin încercare și eroare. Ideea este de a introduce date care creează interogări în care apar posibile nume ale câmpurilor. În cazul în care interogările dau o eroare, înseamnă că numele este incorect, dacă nu, înseamnă că am primit numele câmpurilor corect.

De exemplu, vom testa dacă numele unuia dintre câmpuri este „utilizator”.

Am putea face ceva similar cu ceea ce s-a văzut în punctul anterior:

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Eroare de interogare.

Răspunsul aplicației este „Eroare interogare”, care indică faptul că nu există un câmp numit „utilizator”. În acest caz, interogarea către baza de date va fi fost așa:

O altă posibilă intrare ar fi putut fi următoarea:

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Eroare de interogare.

Răspunsul aplicației este „Eroare interogare”, care indică faptul că nu există un câmp numit „utilizator”. În acest caz, interogarea către baza de date va fi fost așa:

În SQL, cratimele sunt semnul de început al unui comentariu, deci citatul final nu este luat în considerare în interogare.

În ambele cazuri am obținut „Eroare la interogare”, deci știm că niciun câmp nu se numește „utilizator”.

Acum facem oa doua încercare, cu numele „utilizator”

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Nume de utilizator incorect.

În acest caz, interogarea bazei de date va fi ceva de genul acesta:

Deoarece am primit răspunsul „Nume de utilizator rău”, știm că unul dintre câmpuri se numește „utilizator”.

SQL Injection 3 - Aflați numele tabelelor

Numele tabelelor pot fi găsite prin încercare și eroare. Ideea este de a introduce date care creează interogări în care apar posibile nume ale tabelelor. În cazul în care interogările dau o eroare, înseamnă că numele este incorect, dacă nu, înseamnă că am ghicit numele tabelelor.

De exemplu, să testăm dacă numele tabelului este „utilizatori”.

Am putea face ceva similar cu cel văzut în punctul anterior:

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Eroare de interogare.

Răspunsul aplicației este „Interogarea eșuată”, ceea ce ne spune că nu există un tabel numit „utilizatori”. În acest caz, interogarea către baza de date va fi fost așa:

Acum facem o a doua încercare, cu numele „tabel”

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Nume de utilizator incorect.

În acest caz, interogarea bazei de date va fi ceva de genul acesta:

Deoarece am primit răspunsul „Nume de utilizator rău”, știm că unul dintre tabele se numește „tabel”.

SQL Injection 4 - Aflați conținutul registrelor

Odată ce numele tabelului utilizatorului și numele câmpurilor sunt cunoscute, este posibil să încercați să cunoașteți valorile specifice ale unei înregistrări prin încercare și eroare. Ideea este de a introduce date care construiesc interogări în care să apară conținutul posibil al câmpurilor. În cazul în care interogările dau o eroare, înseamnă că conținutul este incorect, dacă nu, înseamnă că avem conținutul corect.

De exemplu, să căutăm nume de utilizator.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Corectați numele de utilizator și parola.

Răspunsul din aplicație este „Corectați numele de utilizator și parola.”, Ceea ce indică faptul că există un utilizator al cărui nume începe cu „a”. În acest caz, interogarea către baza de date va fi fost așa:

Am putea prelungi șirul literă cu literă până când vom găsi numele utilizatorului.

Injecție SQL 5 - Adăugați un utilizator nou

Notă: Acest tip de atac nu funcționează în aplicația de exemplu din prima secțiune a acestei lecții, deoarece extensia PDO nu permite executarea mai multor interogări simultan, dar funcționează în aplicația vulnerabilă injection_sql_2.zip pe care o puteți testa pe computer.

Odată ce cunoașteți numele tabelului de utilizatori și numele câmpurilor, puteți încerca să editați baza de date, de exemplu, adăugând un utilizator.

Tehnica constă în includerea unei instrucțiuni SQL care introduce o înregistrare.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Nume de utilizator incorect

În acest caz, interogarea bazei de date va fi ceva de genul acesta:

Pentru a verifica dacă atacul a avut succes, ar trebui să încercați să introduceți ca utilizator „hacker” cu o parolă „hacker”.

Evident, pentru ca atacul să aibă succes, ar fi trebuit să avem structura tabelului corectă, care ar putea necesita teste extinse sau ar putea fi prea dificilă. O altă modalitate de a obține datele unui utilizator ar fi să aflați numele unui utilizator (prin declarații LIKE și o oarecare răbdare) și să injectați o interogare care să le schimbe parola.

Injecție SQL 6 - Plasați un tabel

Notă: Acest tip de atac nu funcționează în aplicația de exemplu din prima secțiune a acestei lecții, deoarece extensia PDO nu permite executarea mai multor interogări simultan, dar funcționează în aplicația vulnerabilă injection_sql_2.zip pe care o puteți testa pe computer.

Odată ce numele tabelului utilizator este cunoscut, vom efectua o acțiune distructivă, cum ar fi ștergerea tabelului utilizator.

Tehnica constă în includerea unei instrucțiuni SQL care introduce o înregistrare.

Pentru a intra în sistem, introduceți numele de utilizator și parola:

Utilizator:
Parola:

Nume de utilizator incorect

Eroare de interogare.

În acest caz, interogarea bazei de date va fi ceva de genul acesta:

Dacă atacul are succes, aplicația va înceta cu siguranță să funcționeze, deoarece unul dintre tabele a dispărut.

A se termina .

Excelenta bandă desenată xkcd a publicat o glumă pe această temă:

introduceți numele

Această pagină a fost modificată ultima dată: 29 noiembrie 2012


Această pagină face parte din curs Programare web PHP de Bartolomé Sintes Marco
care este distribuit sub o licență internațională Creative Commons Attribution-ShareAlike 4.0 (CC BY-SA 4.0).