SQL Injekcijos

Tarkim turime puslapį, kuriame yra tam tikra forma (pvz: registracijos, prisijungimo), kurioje įvesti duomenys tikrinami/įrašomi i SQL bazę (Kaip pavyzdį naudosiu prisijungimo formą). Vieno iš formos įvedimo laukelio vardas yra 'NAME', kuriame reikia įvesti prisijungimo vardą.
Taigi, tokio puslapio, kuris tikrina įvestus duomenis, SQL užklausa turėtų atrodyti daug maž taip:

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = '$NAME';

(PHP pvz: mysql_query("'SELECT name,pass,email FROM users WHERE name='$name'");)

Čia $NAME yra puslapio kintamasis, kuris sudarytas iš formoj įrašyto prisijungimo vardo (PHP pvz: $NAME = $_POST['NAME'];).
Tikslų laukelių ar 'stalo' pavadinimo mes nežinom, bet tai tam tikromis užklausomis ir spėliojimais galima juos sužinuot.
Pamėginus į prisijungimo formą įvesti atsitiktinius vardą ir slaptažodį, mums turėtų parodyti klaidą apie neteisingą slaptažodį ar vartotojo vardą. Jeigu pamėgintume vietoje vartotojo vardo įvesti Vardas', tada SQL užklausa atrodytų taip:

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = 'Vardas'';

Tokia užklausą turėtų mums gražinti pranešimą apie sintaksės klaidą, kadangi užklausos pabaigoje yra dvi apostrofos. Jeigu tikrai gražino tokį pranešimą, reiškia puslapio informaciją nėra filtruojama ir puslapis pažeidžiamas, jei gražino kitokį pranešimą - puslapis saugus.

Dabar pasidarome užklausą kuri visada gražntų teigiamą reikšmę:

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = 'Vardas' OR 'x'='x';

Kadangi x visados bus lygu x, tai ir ši užklausa visada bus 'true'. Su tokia užklausa praeinamas tik vartotojo vardo patikrinimas, iš tiesų ką gražins puslapis neaišku, tai lieka pačiam išssiaiškint pamėginus. Tarkim kad sistema mums gražino pranešima kad netinkamas slaptažodis (Vartotojo vardas atitiko, kadangi užklausa visa gražins 'true' tai neturi reikšmės kas parašytas vardas)

Taigi turime tris pranešimų tipus:

1. Neteisingas vardas. (paprasta, teisinga SQL užklausa)
2. Neteisingasa slaptažodis. (kai vartotojo vardas apeitas)
2. Sintaksės klaida. (blogai suformuluota SQL užklausa)

Iki šiol yra nežinomi lakuų pavadinimai ir nėra funkcijos kurį juos parodytų. Tad dabar prasideda spėliojimas. Pirma pasidaroma užklausa, kuri mums parodys ar SQL užklausa teisinga ir leis atspėti laukelių pavadinimus.

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = 'x' AND email IS NULL; --';

Kadangi mums dabar vardas nerūpi, tai jis yra x. Čia 'email' yra spėjamo lauko pavadinimas. Jei gauname pranešimą kad SQL sintaksė bloga, vadinasi laukelio pavadinimas netoks, o jei gražina kad neteisingas vartotojas - vadinasi jau žinomas laukelio pavadinimas. Taigi taip atspėti galima ir kitus laukeliu pavadinimus.

Kadangi šis straipsins skirtas apsisaugoti nuo SQL Injection, tad nematau prasmės aiškint kaip viskas vyksta toliau, tik pateiksiu keletą pavyzdžių. Iš viso to jau turėtumete susidaryti bendrą vaizdą, kaip viskas vyksta.

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = 'x'; UPDATE users SET email = 'lauzinetojo@email.addr' WHERE user = 'admin' ';

SELECT laukeliu_pavadinimai
FROM table_pav
WHERE laukelio_pav = 'x'; DROP TABLE users; --';


Apsisaugojimas.

Nuo viso to galima apsisaugoti labai paprastai - naudojant tam tikras funkcijas, kurios neleidžia kartotis apostrofom.
PHP tam skirta funkcija yra mysql_escape_string(); - ši funkcija visas apostrofas pakeis į \', todėl šios apostrofos nebus skaitomos kaip užklausos sintaksės dalis.

Žinoma yra ir kitų būdų kaip apsisaugot. Pvz.: galima su Regular Expresions patikrint ir neleisti įvesti tokių simbolių kaip apostrofos, arba dar galima iš įvedamo teksto ištrinti tokius simbolius.

©scripterz.linija.net
Data: 2009-04-20 20:01:26, Autorius: Paulius

Rašyti komentarą

Prašome prisijungti!
arrow_upward