logo

SQL įpurškimas

SQL įpurškimas yra žiniatinklio programų saugos trūkumas, kai užpuolikai įterpia žalingą SQL kodą naudotojo įvestyje. Tai gali leisti jiems pasiekti jautrius duomenis, keisti duomenų bazės turinį arba net perimti sistemos valdymą. Svarbu žinoti apie SQL injekciją, kad žiniatinklio programos būtų saugios.

SQL injekcija (SQLi) yra saugos pažeidžiamumas, atsirandantis, kai užpuolikas gali manipuliuoti žiniatinklio programos duomenų bazės užklausomis į vartotojo įvesties laukus įterpdamas kenkėjišką SQL kodą. Šios įvestos užklausos gali manipuliuoti pagrindine duomenų baze, kad būtų galima atkurti arba ištrinti neskelbtinus duomenis. Kai kuriais atvejais užpuolikai gali netgi padidinti teises, įgydami visišką duomenų bazės ar serverio valdymą.



sql injekcija' title=

Realaus pasaulio pavyzdys:

2019 m. „Capital One“ duomenų pažeidimas įvyko dėl netinkamai sukonfigūruotos žiniatinklio programos, leidžiančios užpuolikui išnaudoti SQL injekcijos pažeidžiamumą. Dėl to buvo nutekėję daugiau nei 100 milijonų klientų asmens duomenys, įskaitant vardus, adresus ir kredito balus.

SQL įpurškimo saugos lygis

DVWA suteikia keturis SQL įpurškimo saugos lygius, kad padėtų besimokantiesiems pamatyti, kaip įvairios apsaugos veikia atakas:



1. Žemas saugumas

Programa priima jūsų įvestį ir tiesiogiai įdeda ją į SQL užklausą be filtravimo.

$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';
  • Įeinant ': Sulaužo užklausą ir priverčia duomenų bazę įvesti klaidą, atskleidžiančią, kad ji yra pažeidžiama.
  • Įeinant 1' OR '1'='1: Apgaudinėja, kad užklausa visada būtų teisinga, kad būtų grąžinti visi vartotojai.
  • Įeinant 1' UNION SELECT user password FROM users--: Prisijungia prie kitos užklausos, kad gautų paslėptus duomenis, pvz., naudotojų vardus ir slaptažodžius.

2. Vidutinis saugumas

Programa taiko pagrindinį įvesties valymą naudodama tokias funkcijas kaipaddslashes()pabėgti'.

$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';

Kaip gali būti ataka:



Paprastas'injekcija nebeveiks (nes ji tampa').

Tačiau užpuolikai vis tiek gali apeiti naudodami skaičių įterpimą (nes skaičiams nereikia kabučių).
Pavyzdys:

prisijungti prie duomenų bazės java
1 OR 1=1

Tai vis tiek grąžina visus įrašus.

3. Aukštas saugumas

Programėlė naudoja paruoštus teiginius (parametrizuotas užklausas), kad saugiai tvarkytų vartotojo įvestį.

$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);

Ataka:

Bandymai kaip' OR 1=1arbaUNION SELECTnebedirba.

Užklausa traktuoja visą įvestį kaip duomenis, o ne SQL kodą.

SQL įpurškimo tipai

Yra įvairių SQL įpurškimo tipų

1. Klaidomis pagrįstas SQL įpurškimas

Klaidomis pagrįstas SQL įterpimas yra SQL įterpimo juostoje tipas, kai užpuolikas tyčia priverčia duomenų bazę generuoti klaidos pranešimą. Tada užpuolikas analizuoja šį klaidos pranešimą, kad gautų vertingos informacijos apie duomenų bazės struktūrą, pvz., lentelių pavadinimus ir stulpelių pavadinimus, kurie gali būti naudojami tolimesnėms tikslesnėms atakoms kurti.

Kaip tai veikia

Ši ataka nukreipta į programas, kurios atskleidžia neapdorotas duomenų bazės klaidas, o ne rodo bendruosius pranešimus. Įvesdami kenkėjišką įvestį, pažeidžiančią SQL sintaksę, užpuolikai sukelia šias klaidas ir gauna vertingų duomenų apie duomenų bazės struktūrą.

java konstanta
  1. Nustatykite pažeidžiamą įvestį: Užpuolikas randa įvesties lauką, pvz., paieškos juostą arba URL parametrą, kuris tiesiogiai sąveikauja su duomenų baze be tinkamo įvesties valymo.
  2. Įleisti kenksmingą naudingą apkrovą: Užpuolikas įveda specialų simbolį (pvz., vieną citatą') arba funkcija, kuri, kaip žinoma, sukelia duomenų bazės klaidą.
  3. Išanalizuokite klaidą: Duomenų bazė, negalinti apdoroti netinkamai suformuotos užklausos, pateikia išsamų klaidos pranešimą. Šis pranešimas gali atskleisti svarbią informaciją, pvz.:
    • Duomenų bazės sistema (pvz., MySQL Oracle SQL Server).
    • Duomenų bazės versija.
    • Vykdoma visa SQL užklausa.
    • Konkrečios sintaksės klaidos, kurias galima naudoti norint suprasti lentelių ar stulpelių pavadinimus.
  4. Patikslinkite ataką: Naudodamas informaciją, surinktą iš klaidos pranešimo, užpuolikas gali patobulinti savo naudingą apkrovą, kad gautų daugiau duomenų, pvz., naudotojų vardų ir slaptažodžių.

Pavyzdys:

1 veiksmas: nustatykite savo aplinką

  • Paleiskite DVWA. Paprastai jis pasiekiamas naršant į tokį URL kaiphttp://localhost/dvwasavo naršyklėje.
failą' loading='lazy' title=
  • Prisijunkite prie DVWA naudodami numatytuosius kredencialus:admin/password.
failą' loading='lazy' title=
  • Eikite į skirtuką DVWA sauga ir nustatykite žemą saugos lygį. Tai užtikrins, kad pažeidžiamumas bus lengvai išnaudojamas.
failą' loading='lazy' title=

2 veiksmas: nustatykite pažeidžiamumą

SQL įpurškimo puslapyje yra paprastas įvesties laukelis, kuriame galite įvesti vartotojo ID. Užpakalinė užklausa greičiausiai yra kažkas panašausSELECT * FROM users WHERE id = 'user_input'

  • Įveskite galiojantį ID kaip1į įvesties laukelį ir spustelėkite „Pateikti“. Turėtumėte matyti išsamią vartotojo, kurio ID 1, informaciją.
failą' loading='lazy' title=

SQL įpurškimo šaltinis

PHP
 $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?>
  • Dabar pabandykite nutraukti užklausą. Įveskite vieną citatą'įvesties laukelyje ir pateikite.
failą' loading='lazy' title=

Užklausa tampa tokia:

SELECT * FROM users WHERE id = ''';

Čia duomenų bazė mato papildomą citatą ir nežino, kaip užpildyti užklausą.

importo ant

Užuot rodydama išsamią vartotojo informaciją, programa pateiks SQL klaidą (kažkas panašaus į „Jūsų SQL sintaksėje įvyko klaida...“)

Tai vadinama klaida pagrįstu SQL įpurškimu, nes:

  • Užpuolikas siunčia neteisingą įvestį (')
  • Duomenų bazė pateikia klaidą
  • Dėl šios klaidos nutekinama naudinga informacija apie duomenų bazę (pvz., DB stulpelių skaičiaus struktūros tipas ir kt.)

2. Sąjungoje pagrįstas SQL įpurškimas

Sąjungoje pagrįsta SQL įpurškimas yra technika, kai užpuolikai naudojaUNIONoperatorius gali sujungti dviejų ar daugiau rezultatųSELECTteiginius į vieną rezultatų rinkinį. Tai gali leisti jiems išgauti informaciją iš kitų duomenų bazės lentelių. TheUNIONoperatorius gali būti naudojamas tik jei:

  • Abiejose užklausose yra tiek pat stulpelių
  • Stulpelių duomenų tipai yra panašūs
  • Stulpeliai yra ta pačia tvarka

SĄJUNGOS operatorius :UNIONoperatorius naudojamas dviejų ar daugiau rezultatų rinkiniui sujungtiSELECTpareiškimus.

  • KiekvienasSELECTpareiškimas vidujeUNIONturi turėti tiek pat stulpelių
  • Stulpelių duomenų tipai turi būti panašūs
  • Stulpeliai turi būti ta pačia tvarka
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2

Pavyzdys:

1 veiksmas: Pirmiausia turime rasti svetainėje esamos lentelės stulpelių skaičių, kad galėtume įvesti UNION pagrįstą SQL įpurškimą:

SQL įpurškimo puslapyje yra paprastas įvesties laukelis, kuriame galite įvesti vartotojo ID. Užpakalinė užklausa greičiausiai yra kažkas panašaus

 SELECT * FROM users WHERE id = 'user_input'

Dabar pabandykite nutraukti užklausą. Įveskite vieną citatą'įvesties laukelyje ir pateikite.

Jei programa yra pažeidžiama, gausite išsamų klaidos pranešimą. Tai gali atrodyti maždaug taip:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1

2 veiksmas: NaudokiteUNIONRaktažodis stulpelių skaičiui sužinoti

Norėdami naudotiUNIONraktinį žodį (dažnas kitas veiksmas), turite žinoti pradinės užklausos stulpelių skaičių. Tai galite sužinoti naudodamiORDER BYsąlyga

komanda arp-a
  • Pabandykite rūšiuoti rezultatus pagal stulpelius
1: 1 ORDER BY 1. 
  • Pateikti. Turėtų veikti.
failą' loading='lazy' title=

SQL įpurškimo šaltinis

PHP
 if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( '
' . ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '
'
); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo '
ID: {$id}  
First name:
{$first}
Surname:
{$last}
'
; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?>
  • Padidinkite skaičių:
 1 ORDER BY 2. 

Pateikti. Turėtų veikti.

failą' loading='lazy' title=
  • Didinkite, kol gausite klaidą. Pavyzdžiui1 ORDER BY 4gali jums duoti:Unknown column '4' in 'order clause'
  • Tai reiškia, kad užklausoje yra 3 stulpeliai.

3. Aklas SQL įpurškimas

Aklas SQL įpurškimas įvyksta, kai užpuolikai negali matyti užklausos rezultatų tiesiogiai tinklalapyje. Vietoj to jie pateikia informaciją iš subtilių programos veikimo ar reakcijos laiko pokyčių. Nors lėtesnis ir nuobodesnis nei klasikinis SQLi, jis gali būti toks pat veiksmingas.

Užuot atgavę duomenis, užpuolikas nustato informaciją stebėdamas tinklalapio elgesį. Paprastai tai daroma vienu iš dviejų būdų:

  1. Būlio pagrindu sukurtas aklas SQLi: Užpuolikas įveda SQL užklausą, kuri grąžina a tiesa arba klaidinga rezultatas. Žiniatinklio programos atsakymas keičiasi atsižvelgiant į tai, ar užklausa teisinga, ar klaidinga. Pavyzdžiui, puslapyje gali būti rodomas kitas pranešimas arba kitoks išdėstymas.
  2. Laiku pagrįstas aklas SQLi: Užpuolikas įveda SQL užklausą, dėl kurios duomenų bazė atlieka daug laiko reikalaujantį veiksmą (pvz.SLEEP()funkcija), jei įvykdoma sąlyga. Užpuolikas stebi laiką, per kurį puslapis įkeliamas, kad nustatytų, ar įterpta sąlyga buvo teisinga, ar klaidinga.

Pavyzdys:

Įsivaizduokite prisijungimo puslapį, kuriame įvesite vartotojo vardą ir slaptažodį. Programa sukuria SQL užklausą taip:

SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'

Aklas SQL injekcija apimtų manipuliavimąuser_inputlauke, kad užduotų duomenų bazei klausimą.

Užuot gavęs tiesioginį atsakymą, užpuolikas gali pabandyti kažką panašaus:

user_input = 'admin' AND 1=1; --

Jei puslapis įkeliamas įprastai, užpuolikas tai žino1=1yra a tiesa pareiškimas.

user_input = 'admin' AND 1=2; --

Jei puslapyje rodoma klaida arba jis elgiasi kitaip, užpuolikas tai žino1=2yra a klaidinga pareiškimas.

failą' loading='lazy' title=

Naudodamas šių teisingų / klaidingų klausimų seriją, užpuolikas gali sistemingai atspėti ir išgauti informaciją po vieną simbolį. Procesas gali būti automatizuotas, kad būtų galima atspėti viską nuo lentelių pavadinimų iki vartotojo slaptažodžių.

SQL įpurškimo atakų poveikis

  • Neteisėta prieiga prie jautrių duomenų : užpuolikai gali gauti duomenų bazėje saugomą asmeninę finansinę ar konfidencialią informaciją.
  • Duomenų vientisumo problemos : užpuolikai gali keisti ištrinti arba sugadinti svarbius duomenis, kurie turi įtakos programos funkcionalumui.
  • Privilegijų eskalavimas : Užpuolikai gali apeiti autentifikavimo mechanizmus ir įgyti administratoriaus teises.
  • Paslaugos prastovos : SQL injekcija gali perkrauti serverį, dėl ko pablogėja našumas arba sugenda sistema.
  • Žala reputacijai : sėkminga ataka gali stipriai pakenkti organizacijos reputacijai ir dėl to prarasti klientų pasitikėjimą.

SQL įpurškimo atakų prevencija

Yra keletas geriausių praktikos būdų, kaip užkirsti kelią SQL injekcijos atakoms:

1. Naudokite paruoštus teiginius ir parametrizuotas užklausas

Parengti teiginiai ir parametrinės užklausos užtikrina, kad vartotojo įvestis būtų traktuojamos kaip duomenys, o ne kaip SQL užklausos dalis. Šis metodas pašalina SQL įterpimo riziką.

metų buvo išrastas kompiuteris

PHP pavyzdys (naudojant MySQLi):

$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();

2. Naudoti saugomas procedūras

Išsaugotos procedūros yra iš anksto nustatytos SQL užklausos, saugomos duomenų bazėje. Šios procedūros gali padėti išvengti SQL injekcijos, nes jos dinamiškai nesukuria SQL užklausų.

Pavyzdys:

CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;

3. Baltojo sąrašo įvesties patvirtinimas

Prieš naudodami SQL užklausas, įsitikinkite, kad vartotojo įvestis yra patvirtintos. Leiskite tik tam tikrus simbolius ir šablonus, pvz., raidinius ir skaitinius laukus, pvz., naudotojų vardus ar el. pašto adresus.

4. Naudokite ORM Frameworks

Objektų santykio atvaizdavimo (ORM) sistemos, pvz Užmigti arba Esybės struktūra gali padėti išvengti SQL įpurškimo, automatiškai tvarkydamas užklausų generavimą, užkertantį kelią dinaminei užklausai kurti.

5. Apriboti duomenų bazės teises

Suteikite vartotojams minimalius reikiamus duomenų bazės leidimus. Įsitikinkite, kad programos gali atlikti tik būtinus veiksmus (pvz., SELECT INSERT) ir apriboti leidimus, pvz., DROP TABLE arba ALTER.

6. Klaidų tvarkymas

Sukonfigūruokite duomenų bazę ir programą, kad vartotojui nebūtų rodomi išsamūs klaidų pranešimai. Vietoj to registruokite klaidas viduje ir galutiniams vartotojams rodykite bendrus klaidų pranešimus.