Az SQL-injekció egy SQL-adatbázisokkal összefüggő biztonsági hiba kihasználása. A biztonsági hiba egy adatbázis-hozzáférő program programozási hibájából ered. E hibán keresztül egy támadó adatbázisparancsokat illeszthet be és egyéni esettől függően további adatokat olvashat ki az adatbázisból, jogosulatlanul módosíthatja vagy törölheti őket, vagy akár az egész adatbázisszerver irányítását átveheti.
Szükségletek Egy sikeres SQL-injekcióhoz az alábbiak szükségesek: egy támadható SQL-adatbázis, például MySQL, Microsoft SQL Server, Db2 egy alkalmazás, melybe bevihetők adatok, például bejelentkezési maszk, termékkeresés vagy webes kapcsolati ív hogy az alkalmazás ezen adatokat az adatbázisba továbbítsa egy hiba az alkalmazásban adattovábbításkor A hiba abban áll, hogy az alkalmazás a bevitt adatokat nem tiszta adatként továbbítja, hanem ezekből adatbázis-lekérdezést hoz létre, így egy támadó megkísérelheti adatbázis-lekérdezések részeinek célzott irányítását.
Az SQL adatbázis-leíró nyelvben egyes jelek saját jelentéssel rendelkeznek, például: az aposztróf és egyes adatbázisokban az idézőjel karakterláncokat választ el a fordított törtvonal (backslash) a következő jel nem speciális jelkénti értelmezését jelenti a pontosvessző egy adatbázisparancsot választ el az azt követőtől két kötőjel a sor maradékát megjegyzéssé teszi. A dokumentumorientált NoSQL adatbázisokat is érintheti e probléma, például a kapcsos és szögletes zárójelek JSON-objektumot, illetve tömböt jelentenek. E karakterek célzott használata lehetővé teszi a támadás véghezvitelét.
Példa Egy példa egy lekérdezésre, mely egy szerkesztőségi rendszerben adott kategóriából keres: SELECT id, cím, szöveg FROM cikkek WHERE kategória = 'keresett kategória'; A lekérdezés az alábbi részekből áll: A nagybetűs szavak kulcsszavak az SQL-ben, meghatározott jelentéssel. A kisbetűs szavak táblázat-, sor- vagy oszlopnevek az adatbázisban. Az egyszerű idézőjelek közti szöveg egyszerű szöveg. A „keresett kategória” itt csak helykitöltő, melynek helyén a keresett kategóriának kell szerepelnie. Míg az egyik említett jelet se tartalmazza, közvetlenül behelyettesíthető a példalekérdezésbe.
Ha a keresett kategória azonban például Rock ’n’ Roll, így aposztrófot tartalmaz, a helykitöltő naiv cseréje az alábbi lekérdezéshez vezet: SELECT id, cím, szöveg FROM cikkek WHERE kategória = 'Rock 'n' Roll';
Itt jelenik meg az aposztróf kettős jelentése: egyrészt karakterlánc-határoló, másrészt szövegbeli szimbólum. E kettős jelentést az emberek láthatják, de az adatbázis nem tudja megfelelően értelmezni, mivel a lekérdezést kategória = 'Rock '-ként értelmezi, melyet az „n” betű követ, majd aposztrófok közt az ezt követő' Roll' szöveg. Az n szót az adatbázis nem tudja megfelelően kezelni, így a lekérdezésre hibát ír ki.
SQL-injekció akkor áll fenn, ha a támadó a bevitt adatok megfelelő választásával a lekérdezést úgy változtatja meg, hogy bár értelmes a szerkezete, de más a jelentése. Így a látszólag értelmetlen „abcd' OR id < 100 OR kategória = 'b123” az alábbi lekérdezéshez vezet:
SELECT id, cím, szöveg FROM cikkek WHERE kategória = 'abcd' OR id < 100 OR kategória = 'b123';
Ez az adatbázis szempontjából teljesen megfelelő, 3 külön feltételt tartalmaz, melyek egyikének igaznak kell lennie. Az első és a harmadik feltétel a példában azt érik el, hogy az SQL-lekérdezés továbbra is értelmes, és ilyen nevű kategóriák léte az adatbázisban valószínűtlen. Így az egyetlen releváns feltétel az id < 100. Az eredeti, csak adott kategóriájú cikkeket megadó lekérdezésből megfelelő kifejezésválasztással más szerkezetű lekérdezés jött létre, mely a cikkeket azonosítóik alapján keresi, kategóriától függetlenül.
E megváltoztatott SQL-lekérdezéssel egy támadó megláthat neki nem megfelelő adatokat az adatbázisból. Más célzott keresőkifejezésekkel adatok módosíthatók vagy törölhetők esettől függően.
A hiba az SQL-injekcióban a keresési kifejezés egy az egyben történő átvétele az aposztróf és más jelek különleges jelentésének átlátása nélkül. Folyamat
Adatmódosítás
Adott egy szerveren egy find.cgi című szkript cikkek megjelenítésére. A szkript paramétere „ID”, mely később a lekérdezés része. Az alábbi táblázat illusztrálja ezt:
Megfelelő működésCímhttp://webserver/cgi-bin/find.cgi?ID=42Kapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42; SQL-injekcióCímhttp://webserver/cgi-bin/find.cgi?ID=42;UPDATE USER SET TYPE="admin" WHERE ID=23Kapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42;UPDATE USER SET TYPE="admin" WHERE ID=23; A programnak így egy módosított, a felhasználó-adatbázist módosító SQL-parancs küldése történik.
Adatbázisszerver-módosítás
Egy webszerveren weblapkeresésre használatos search.aspx fájl van. A szkript paramétere a keyword, melynek értéke SQL-lekérdezés része. Az alábbi táblázat illusztrálja ezt:
Megfelelő működésCímhttp://webserver/search.aspx?keyword=sqlKapott SQLSELECT url, title FROM myindex WHERE keyword LIKE '%sql%' SQL-injekcióCímhttp://webserver/search.aspx?keyword=sql';GO EXEC cmdshell('shutdown /s') --Kapott SQLSELECT url, title FROM myindex WHERE keyword LIKE '%sql';GO EXEC cmdshell('shutdown /s') --%'
Itt a tulajdonképpeni lekérdezés mellé további parancs került. A két kötőjel (--) az a lekérdezés maradékát, az aposztrófot teszi megjegyzésbe, így az figyelmen kívül marad. A létrehozott lekérdezés lehetővé teszi egy Windows-folyamat végrehajtását, jelen esetben a szerver kikapcsolását (amíg a folyamat adminisztrátori jogosultsággal rendelkezik). Azonban adatok és más információk is kiszivároghatnak így (például a Microsoft SQL Server esetén).
Adatok kikémlelése
Egyes SQL-megvalósításokban elérhető a UNION parancs, lehetővé téve több, közös eredményhalmazt adó SELECT egyidejű végrehajtását. Megfelelően megadott UNION paranccsal bármilyen táblázat és rendszerváltozó kikémlelhető.
Megfelelő működésCímhttp://webserver/cgi-bin/find.cgi?ID=42Kapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42; SQL-injekcióCímhttp://webserver/cgi-bin/find.cgi?ID=42 UNION SELECT login, password, 'x' FROM userKapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42 UNION SELECT login, password, 'x' FROM user;
Az x a UNION SELECT esetén szükséges, mivel minden UNION paranccsal összekapcsolt SELECT parancsnak azonos oszlopszámmal kell rendelkeznie. A támadó az oszlopszámot kitalálhatja, ha e mögé az ID=42 order by x-- szöveget teszi. Ha például az oldal esetén megfelelően jelenik meg, de esetén hiba vagy más lap jelenik meg, a táblázat 8 oszlopos.
Hibásan beállított adatbázisszerver és hozzáféréssel rendelkező, éppen az adatbázishoz kapcsolódó felhasználó esetén, akiről szóló adatokkal szemben történik az SQL-injekció, „Rendszeradatbázis.RendszertáblázatTáblázatlistával” vagy hasonló egyszerű SQL-szintaxissal hozzáférhetők a rendszertáblázatok, és kiolvashatók az adatbázisok táblázatai, lehetővé téve fontos információk megszerzését további támadásokhoz és még nagyobb mértékű rendszerhozzáféréshez.
MySQL-adatbázisrendszerek esetén a rendszer-információk az information_schema adatbázisban szerepelnek.Die Datenbank INFORMATION_SCHEMA. MySQL 5.1 Referenzhandbuch, Kapitel 20 Az alábbi példa bemutatja, hogy tudható meg egy 3 kimeneti oszlopú lekérdezésnél a hozzáférhető adatbázisok szerkezete. Megfelelő működésCímhttp://webserver/cgi-bin/find.cgi?ID=42Kapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42; SQL-injekcióCímhttp://webserver/cgi-bin/find.cgi?ID=42 UNION SELECT 'Adatbázis', 'Táblázat', 'Oszlop' UNION SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE NOT table_schema='information_schema';#%20Kapott SQLSELECT author, subject, text FROM cikkek WHERE ID=42 UNION SELECT 'Adatbázis', 'Táblázat', 'Oszlop' UNION SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE NOT table_schema='information_schema';# ; Egyes adatbázisrendszerek lehetővé teszik ezenkívül fájlok lekérdezéssel való kiadását. Ezzel és a fenti technikákkal, valamint ha az elérési út ismert, tetszőleges, az adatbázis-folyamat által hozzáférhető fájl kiolvasható.
Egy hasonló cím egy MongoDB NoSQL adatbázisban így nézhet ki: Megfelelő működésCímhttp://webserver/cgi-bin/find.cgi?ID=42Kapott kód<code>db.users.find({userID: <i style="background-color:lightgreen">42</i });</code> KódinjekcióCímhttp://webserver/cgi-bin/find.cgi?ID['$ne']=Kapott kóddb.users.find({userID: {'$ne': undefined}}); A $ne jelentése: „nem egyenlő”, a lekérdezés minden, nem üres felhasználónevű felhasználót kiad, vagyis minden felhasználót.
Tetszőleges kód futtatása Egy kevésbé ismert változat egyidejűleg a legveszélyesebb. Ha az adatbázisszerver SELECT … INTO OUTFILE, illetve SELECT … INTO DUMPFILE parancsokat támogat, ezek felhasználhatók az adatbázisszerver fájlrendszerén lévő fájlok létrehozására. Elméletileg így lehetséges tetszőleges kód rendszeren való futtatása, ha az operációs rendszer vagy az adatbázisszervver könyvtárszerkezete írható (ha például gyökérfiókként fut).
Időzített támadások Teljesítménymérő funkciókat támogató adatbázisszerver esetén ezek felhasználhatók adatbázis-szerkezetről szóló információk megismeréséhez. Az adatbázis-tartalmak másolása sokkal tovább tart.
Az alábbi példa MySQL-adatbázisszerveren több másodpercig tart, ha a jelenlegi felhasználó root: SELECT IF(USER() LIKE 'root@%', BENCHMARK(100000,SHA1('test')), 'false'); Ehhezhasonlóak a Boole-támadások, melyek Boole-lekérdezésekkel kísérelnek meg adatbázis-tartalmakat kivonni.
Adminisztrátori jogok megszerzése Egyes adatbázisszervereknél, például a Microsoft SQL Servernél a 2000-es verzióig, a tárolt eljárások, például az Xp_cmdshell automatikusan meghívhatók voltak, és többek között arra is használhatók voltak, hogy az SQL-szerverprogram jogaival futtasson parancsokat. Az újabb verziókban e funkció megszűnt. E lehetőség például operációsrendszer-héj futtatására is alkalmas volt a megtámadott számítógépen.
Sérülékenységek az adatbázisszerverben Néha a szoftverben vannak sérülékenységek. Így például a mysql_real_escape_string() PHP-függvény egy MySQL-szerverben lehetővé tesz SQL-injekció-alapú támadásokat Unicode-jelekkel megfelelően maszkolt bemenetek esetén is. Ez az 5.0.22 verzióban lett javítva (2006. május 24.).
Vak SQL-injekció „Vak” az SQL-injekció, ha egy szerver nem ad vissza leíró hibaüzenetet, melyből kiderül, hogy a lekérdezés sikeres-e. Apró eltérések, például könnyen megkülönböztethető hibaüzenetek vagy jelentősen eltérő válaszidők alapján megtudható, hogy egy lekérdezés sikeres volt-e, vagy hibás volt.
Megakadályozás
Az SQL-injekciók elkerüléséért a felhasználó által megadott adatok nem építendők további intézkedés nélkül SQL-parancsba. A bevitt adatok ellenőrzendők a várt értékek tulajdonságaira. Például a német irányítószámok csak számjegyekből állnak.
Előkészített parancsok A legbiztosabb mód az adatok távoltartása az SQL-értelmezőtől. Ekkor nem kell a bevitelt lerövidíteni. Ez az előkészített parancsok paramétereivel működik. Ekkor az adatok egy már lefordított parancs paraméterei. Így nem történik adatértelmezés, megakadályozva az SQL-injekciót. A tárolt eljárások ezzel szemben nem biztosítanak általános védelmet SQL-injekció ellen, különösen ismeretlen SQL-kód esetén.
Azonban az adatbázisszerver-oldalon is történhetnek biztonsági intézkedések. Például a felhasználó, akit egy adatbázisszervernél egy webalkalmazás hitelesít, csak a neki szükséges jogokkal rendelkezzék. Ez hatástalanítja a támadások legalább egy részét.
Ha egy szerverüzemeltető nem irányítja az alkalmazásait, webalkalmazás-tűzfalakkal (WAF) legalább részben megakadályozhatja a gyenge pontok kihasználását. Alkalmazásirányítástól függetlenül egy szerverüzemeltető célzott WAF-használattal növelheti a biztonságot, mivel sok WAF profilaxist is kínál az akadályozás mellett.