Kaj je injiciranje SQL in kako preprečiti v aplikacijah PHP?

Torej menite, da je vaša baza podatkov SQL zmogljiva in varna pred takojšnjim uničenjem? No, SQL Injection se ne strinja!


Da, o tem govorimo o trenutnem uničevanju, saj tega članka ne želim odpirati z običajno hromo terminologijo “poostritve varnosti” in “preprečevanja zlonamernega dostopa.” SQL Injection je tako star trik v knjigi, da vsi, vsi razvijalci, to zelo dobro poznajo in se dobro zavedajo, kako to preprečiti. Razen tistega nenavadnega, ko zdrsnejo, rezultati pa ne morejo biti nič manj katastrofalni.

Če že veste, kaj je SQL vbrizgavanje, lahko preskočite na zadnjo polovico članka. Toda za tiste, ki se šele pojavljajo na področju spletnega razvoja in sanjajo o prevzemu višjih vlog, je nekaj uvodov na vrsti.

Kaj je vstavljanje SQL?

Ključ do razumevanja SQL Injection je v njegovem imenu: SQL + Injection. Beseda “injiciranje” tukaj nima medicinskih konotacij, ampak je raba glagola “injicirati”. Ti dve besedi skupaj prenašata idejo o vključitvi SQL v spletno aplikacijo.

Vstavljanje SQL v spletno aplikacijo. . . hmmm. . . Ali to sploh ni tako? Da, vendar ne želimo, da napadalec poganja našo bazo podatkov. Naj to razumemo s primerom.

Recimo, da gradite značilno spletno mesto PHP za lokalno trgovino za e-trgovino, zato se odločite dodati takšen kontaktni obrazec:

Tvoje ime

Tvoje sporočilo

In predpostavimo, da datoteka send_message.php shrani vse v bazo podatkov, da lahko lastniki trgovin pozneje preberejo uporabniška sporočila. Morda ima tako kodo:

<?php

$ name = $ _POST [‘ime’];
$ message = $ _POST [‘sporočilo’];

// preverite, ali ta uporabnik že ima sporočilo
mysqli_query ($ conn, "IZBERI * iz sporočil, kjer je ime = $ ime");

// Tukaj druga koda

Torej najprej poskusite preveriti, ali ima ta uporabnik že neprebrano sporočilo. Poizvedba SELECT * iz sporočil, kjer se zdi name = $ name dovolj preprosto, kajne?

NAPIS!

V svoji nedolžnosti smo odprli vrata za takojšnje uničenje naše baze podatkov. Da bi se to zgodilo, mora napadalec izpolnjevati naslednje pogoje:

  • Aplikacija deluje na bazi SQL (danes je skoraj vsaka aplikacija)
  • Trenutna povezava z bazo podatkov ima v bazi dovoljenja za urejanje in brisanje
  • Imena pomembnih tabel lahko ugibamo

Tretja točka pomeni, da zdaj, ko napadalec ve, da vodite trgovino za e-trgovino, zelo verjetno shranjujete podatke o naročilu v tabelo naročil. Oboroženi z vsem tem, vse kar mora napadalec storiti je, da to navede kot svoje ime:

Joe; okrniti naročila ;? Ja, gospod! Poglejmo, kakšna bo poizvedba, ko jo bo izvedel skript PHP:

IZBERI * IZ sporočil, KJE je ime = Joe; okrniti naročila;

V redu, prvi del poizvedbe ima napako v sintaksi (brez navodil okoli “Joe”), podpičje pa prisili, da stroj MySQL začne razlagati novega: skrajšati naročila. Tako pa je v enem samem naletu celotna zgodovina naročil izginila!

Zdaj, ko veste, kako deluje SQL Injection, je čas, da pogledamo, kako ga ustaviti. Dva pogoja, ki ju je treba izpolniti za uspešno injiciranje SQL, sta:

  1. Skript PHP bi moral spremeniti / izbrisati privilegije v bazi podatkov. Mislim, da to velja za vse aplikacije in ne boste mogli narediti svojih aplikacij samo za branje. �� In ugibajte, kaj, tudi če odstranimo vse privilegije za spreminjanje, lahko vbrizgavanje SQL nekomu še vedno omogoči izvajanje SELECT poizvedb in ogled vseh podatkovnih zbirk, vključno z občutljivimi podatki. Z drugimi besedami, zmanjšanje ravni dostopa do baze podatkov ne deluje in vaša aplikacija jo tako ali tako potrebuje.
  2. Uporabniški vnos je v obdelavi. Edino, kako lahko injekcija SQL deluje, je sprejemanje podatkov od uporabnikov. Še enkrat ni praktično zaustaviti vseh vnosov za vašo aplikacijo samo zato, ker vas skrbi injekcija SQL.

Preprečevanje injekcije SQL v PHP

Glede na to, da so povezave z bazo podatkov, poizvedbe in vnosi uporabnikov del življenja, kako preprečimo brizganje SQL? Na srečo je precej preprosto in obstajata dva načina: 1) sanitizirati uporabniški vnos in 2) uporabiti pripravljene izjave.

Sanitizirajte uporabnikov vnos

Če uporabljate starejšo različico PHP (5.5 ali novejšo različico in se to pogosto dogaja pri skupnem gostovanju), je pametno zagnati ves uporabniški vnos s pomočjo funkcije, imenovane mysql_real_escape_string (). V bistvu to, kar počne, odstrani vse posebne znake v nizu, tako da izgubijo pomen, ko jih uporablja baza podatkov.

Na primer, če imate niz, kot sem niz, lahko napadalec uporabi sam znak citata (‘) za manipulacijo poizvedbe po zbirki podatkov in povzroči vbrizgavanje SQL. Če ga izvajate preko mysql_real_escape_string (), dobim niz, ki enemu ponudniku doda povratno poševnico in jo umakne. Posledično se celoten niz zdaj v bazo podatkov prenese kot neškodljiv niz, namesto da bi lahko sodeloval v manipulaciji s poizvedbami.

Pri tem pristopu je ena pomanjkljivost: gre za resnično resnično staro tehniko, ki ustreza starejšim oblikam dostopa do baze podatkov v PHP. Kot v PHP 7, ta funkcija sploh ne obstaja več, kar nas pripelje do naše naslednje rešitve.

Uporabite pripravljene izjave

Pripravljene izjave so način za varnejšo in zanesljivejšo poizvedbo po zbirki podatkov. Ideja je, da namesto da pošljemo surovo poizvedbo v bazo, najprej povemo strukturi poizvedbe, ki jo bomo poslali. To mislimo s “pripravo” izjave. Ko je izjava pripravljena, podatke posredujemo kot parametrizirane vhode, tako da lahko baza podatkov “zapolni vrzeli” s priključitvijo vhodov v strukturo poizvedb, ki smo jo poslali prej. To odvzame vsako posebno moč, ki jo imajo vhodi, zaradi česar se v celotnem postopku obravnavajo kot zgolj spremenljivke (ali koristne obremenitve). Takole izgledajo pripravljene izjave:

<?php
$ servername = "lokalni gostitelj";
$ username = "uporabniško ime";
$ geslo = "geslo";
$ dbname = "myDB";

// Ustvari povezavo
$ conn = novi mysqli (ime strežnika, uporabniško ime $, geslo $, ime dbname);

// Preverite povezavo
če ($ kon->connect_error) {
umreti ("Povezava ni uspela: " . $ conn->connect_error);
}

// pripraviti in vezati
$ stmt = $ conn->pripraviti ("VSTAVITE V MyGuests (ime, priimek, e-pošta) VREDNOSTI (?,?,?)");
$ stmt->bind_param ("sss", $ ime, $ priimek, $ e-pošta);

// nastavite parametre in izvedite
$ name = "John";
$ priimek = "Doe";
$ email = "[zaščitena e-pošta]";
$ stmt->izvršiti ();

$ name = "Marija";
$ priimek = "Moe";
$ email = "[zaščitena e-pošta]";
$ stmt->izvršiti ();

$ name = "Julie";
$ priimek = "Dooley";
$ email = "[zaščitena e-pošta]";
$ stmt->izvršiti ();

odmev "Uspešno so bili ustvarjeni novi zapisi";

$ stmt->blizu ();
$ conn->blizu ();
?>

Vem, da se postopek sliši po nepotrebnem zapleteno, če ste novi v pripravljenih izjavah, vendar je koncept vreden truda. Tukaj je lep uvod v to.

Za tiste, ki že poznate PHP-jevo razširitev PDO in jo uporabljate za ustvarjanje pripravljenih izjav, imam majhen nasvet.

Opozorilo: Bodite previdni pri nastavitvi PDO

Pri uporabi PDO za dostop do baze podatkov se lahko zaničimo v lažni občutek varnosti. “Ah, no, uporabljam ZOP. Zdaj mi ni treba razmišljati o ničemer drugem. “- tako nekako razmišlja naše razmišljanje. Res je, da je PDO (ali MySQLi pripravljene izjave) dovolj za preprečevanje vseh vrst napadov vbrizgavanja SQL, vendar morate biti pozorni pri nastavitvi. Običajno je, da samo kopirate in prilepite kodo iz vaj ali iz prejšnjih projektov in nadaljujete, vendar lahko ta nastavitev razveljavi vse:

$ dbPrivezava->setAttribute (PDO :: ATTR_EMULATE_PREPARES, res);

Ta nastavitev je ta, da PDO pove, da posnemajo pripravljene izjave, namesto da dejansko uporabljajo funkcijo pripravljenih stavkov v bazi. Posledično PHP v bazo pošlje preproste poizvedbene nize, tudi če vaša koda izgleda, da ustvarja pripravljene izjave in nastavlja parametre in vse to. Z drugimi besedami, vi ste tako ranljivi za injiciranje SQL kot prej. ��

Rešitev je preprosta: preverite, ali je ta emulacija nastavljena na napačno.

$ dbPrivezava->setAttribute (PDO :: ATTR_EMULATE_PREPARES, napačno);

Zdaj je PHP skript prisiljen uporabljati pripravljene izjave na ravni baze podatkov, da prepreči vse vrste vbrizgavanja SQL.

Preprečevanje uporabe WAF

Ali veste, da lahko spletne aplikacije zaščitite tudi pred injiciranjem SQL z uporabo WAF (požarni zid spletne aplikacije)?

No, ne samo vbrizgavanje SQL, ampak tudi številne druge ranljivosti 7 plasti 7, kot so skrivnost na spletnem mestu, prekinjena avtentikacija, ponarejanje na spletnih mestih, izpostavljenost podatkov itd. Uporabite lahko samostojno gostovanje kot Mod Security ali oblak kot naslednje:.

SQL injekcija in sodobni PHP okviri

Vbrizgavanje SQL je tako pogosto, tako enostavno, tako frustrirajoče in tako nevarno, da so vsi sodobni spletni okviri PHP vgrajeni s protiukrepi. V WordPressu imamo na primer $ wpdb->pripravi () funkcijo, medtem ko uporabljate okvir MVC, vam vse to umazanijo in vam sploh ni treba razmišljati o preprečevanju vbrizgavanja SQL. Malo je nadležno, da morate v WordPressu izrecno pripraviti izjave, ampak hej, o tem govorimo o WordPressu. ��

Kakorkoli že, poantiram, da sodobna pasma spletnih razvijalcev ni treba razmišljati o vbrizgavanju SQL-a, zato se sploh ne zavedajo možnosti. Tudi če v svoji aplikaciji pustijo odprto zaledje (morda gre za parameter poizvedbe $ _GET in stare navade, da se sproži umazana poizvedba), so lahko rezultati katastrofalni. Zato si je vedno bolje vzeti čas, da se potopite globlje v temelje.

Zaključek

SQL Injection je zelo grd napad na spletno aplikacijo, ki pa se mu je enostavno izogniti. Kot smo videli v tem članku, je previdnost pri obdelavi uporabniškega vnosa (mimogrede, SQL Injection ni edina grožnja, ki jo prinaša ravnanje z uporabniškim vnosom) in poizvedovanje po zbirki podatkov je zanjo vse. Glede na to ne delujemo vedno na področju varnosti spletnega okvira, zato je bolje, da se zavedate tovrstnih napadov in ne sodite nanje.

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map