SQL Injekció
Az SQL Injection a webalkalmazások biztonsági hibája, ahol a támadók káros SQL-kódot szúrnak be a felhasználói bevitellel. Ez lehetővé teszi számukra, hogy hozzáférjenek az érzékeny adatokhoz, módosítsák az adatbázis tartalmát, vagy akár átvegyék a rendszer irányítását. A webalkalmazások biztonságának megőrzése érdekében fontos tudni az SQL Injectiont.
Az SQL-injekció (SQLi) egy biztonsági rés, amely akkor fordul elő, ha a támadó manipulálni tudja egy webalkalmazás adatbázis-lekérdezését úgy, hogy rosszindulatú SQL-kódot szúr be a felhasználói beviteli mezőkbe. Ezek a beszúrt lekérdezések manipulálhatják az alapul szolgáló adatbázist érzékeny adatok módosítása vagy törlése érdekében. Egyes esetekben a támadók akár kiterjeszthetik is a jogosultságokat, hogy teljes irányítást szerezzenek az adatbázis vagy a kiszolgáló felett.
Valós példa:
2019-ben a Capital One Data Breach egy rosszul konfigurált webalkalmazás miatt következett be, amely lehetővé tette a támadók számára, hogy kihasználják az SQL-befecskendezési sebezhetőséget. Ennek eredményeként több mint 100 millió ügyfél személyes adatai szivárogtak ki, beleértve a neveket, címeket és hitelképességi pontszámokat.
SQL Injection biztonsági szint
A DVWA négy biztonsági szintet biztosít az SQL Injection számára, hogy segítse a tanulókat abban, hogy meglássák, hogyan hatnak a különböző védelmek a támadásokra:
1. Alacsony biztonság
Az alkalmazás fogadja a bemenetet, és szűrés nélkül közvetlenül az SQL-lekérdezésbe helyezi.
$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; - Belépés
':Megszakítja a lekérdezést, és az adatbázis hibát dob, jelezve, hogy sebezhető. - Belépés
1' OR '1'='1:Becsapja a lekérdezést, hogy mindig igaz legyen, így minden felhasználó visszakerül. - Belépés
1' UNION SELECT user password FROM users--:Egy másik lekérdezéshez csatlakozik a rejtett adatok, például a felhasználónevek és jelszavak lekéréséhez.
2. Közepes biztonság
Az alkalmazás alapvető bemeneti fertőtlenítést alkalmaz olyan funkciók segítségével, mint addslashes() megszökni ' .
$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';Hogyan lehet támadás:
Egy egyszerű
'az injekció többé nem fog működni (mert azzá válik').De a támadók továbbra is megkerülhetik a numerikus injekciót (mivel a számokhoz nem kell idézőjel).
Példa:1 OR 1=1Ez továbbra is visszaadja az összes rekordot.
3. Magas biztonság
Az alkalmazás előkészített utasításokat (paraméterezett lekérdezéseket) használ a felhasználói bevitel biztonságos kezelésére.
$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);Támadás:
Olyan próbálkozások, mint
'OR 1=1vagyUNION SELECTmár nem működik.A lekérdezés minden bemenetet adatként kezel, nem SQL-kódként.
Az SQL-befecskendezés típusai
Az SQL-injekciónak különböző típusai vannak
1. Hibaalapú SQL-injekció
A hibaalapú SQL-befecskendezés a sávon belüli SQL-befecskendezés egy olyan típusa, ahol a támadó szándékosan hibaüzenetet generál az adatbázisban. A támadó ezt követően elemzi ezt a hibaüzenetet, hogy értékes információkat szerezzen az adatbázis szerkezetéről, például táblanevekről és oszlopnevekről, amelyek segítségével további pontosabb támadásokat hozhat létre.
Hogyan működik
Ez a támadás olyan alkalmazásokat céloz, amelyek általános üzenetek megjelenítése helyett nyers adatbázishibákat tárnak fel. Az SQL szintaxist megtörő rosszindulatú bevitel beszúrásával a támadók ezeket a hibákat váltják ki, és értékes nyomokat nyernek az adatbázis szerkezetéről.
- Sebezhető bemenet azonosítása: A támadó talál egy beviteli mezőt, például egy keresősávot vagy egy URL-paramétert, amely közvetlenül kölcsönhatásba lép az adatbázissal, megfelelő beviteli fertőtlenítés nélkül.
- Rosszindulatú rakomány beadása: A támadó bead egy speciális karaktert (például egyetlen idézetet
') vagy egy olyan függvény, amelyről ismert, hogy adatbázishibát okoz.- A hiba elemzése: Az adatbázis nem tudja feldolgozni a hibás lekérdezést, részletes hibaüzenetet ad vissza. Ez az üzenet olyan fontos információkat fedhet fel, mint például:
- Az adatbázisrendszer (pl. MySQL Oracle SQL Server).
- Az adatbázis verziója.
- A teljes SQL lekérdezés végrehajtása folyamatban van.
- Konkrét szintaktikai hibák, amelyek a tábla- vagy oszlopnevek megértéséhez használhatók.
- A támadás finomítása: A hibaüzenetből összegyűjtött információk felhasználásával a támadó finomítani tudja a hasznos terhelést, hogy több adatot, például felhasználóneveket és jelszavakat nyerjen ki.
Példa:
1. lépés: Állítsa be környezetét
- Indítsa el a DVWA-t. Általában egy URL-hez való navigálással érhető el
http://localhost/dvwaa böngészőjében.
- Jelentkezzen be a DVWA-ba az alapértelmezett hitelesítő adatokkal:
admin/password.
- Lépjen a DVWA Security fülre, és állítsa a biztonsági szintet alacsonyra. Ez biztosítja, hogy a sérülékenységek könnyen kihasználhatók legyenek.
2. lépés: Azonosítsa a sebezhetőséget
Az SQL Injection oldalon van egy egyszerű beviteli mező, ahol megadhatja a felhasználói azonosítót. A háttérlekérdezés valószínűleg valami ilyesmi SELECT * FROM users WHERE id = 'user_input'
- Adjon meg egy érvényes azonosítót, mint például
1a beviteli mezőbe, és kattintson a "Küldés" gombra. Látnia kell az 1-es azonosítójú felhasználó adatait.
SQL beadási forrás
PHP $id = $_REQUEST [ 'id' ]; switch ( $_DVWA [ 'SQLI_DB' ]) { case MYSQL : // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = ' $id ';' ; $result = mysqli_query ( $GLOBALS [ '___mysqli_ston' ] $query ) or die ( ' '
. (( is_object ( $GLOBALS [ '___mysqli_ston' ])) ? mysqli_error ( $GLOBALS [ '___mysqli_ston' ]) : (( $___mysqli_res = mysqli_connect_error ()) ? $___mysqli_res : false )) . '
' ); // Get results while ( $row = mysqli_fetch_assoc ( $result ) ) { // Get values $first = $row [ 'first_name' ]; $last = $row [ 'last_name' ]; // Feedback for end user echo ' ID:
{ $id }
First name: { $first }
Surname: { $last } ' ; } mysqli_close ( $GLOBALS [ '___mysqli_ston' ]); break ; case SQLITE : global $sqlite_db_connection ; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = ' $id ';' ; #print $query; try { $results = $sqlite_db_connection -> query ( $query ); } catch ( Exception $e ) { echo 'Caught exception: ' . $e -> getMessage (); exit (); } if ( $results ) { while ( $row = $results -> fetchArray ()) { // Get values $first = $row [ 'first_name' ]; $last = $row [ 'last_name' ]; // Feedback for end user echo ' ID:
{ $id }
First name: { $first }
Surname: { $last } ' ; } } else { echo 'Error in fetch ' . $sqlite_db -> lastErrorMsg (); } break ; } } ode ?> - Most próbálja megszakítani a lekérdezést. Adjon meg egyetlen idézetet
'a beviteli mezőbe, és küldje el.
A lekérdezés a következő lesz:
SELECT * FROM users WHERE id = ''';Itt az adatbázis egy extra árajánlatot lát, és nem tudja, hogyan fejezze be a lekérdezést.
A felhasználói adatok megjelenítése helyett az alkalmazás SQL-hibát ad vissza (ilyen például: „Hiba van az SQL-szintaxisban…”)
Ezt hívják hibaalapú SQL-injekciónak, mert:
- A támadó érvénytelen bevitelt küld (
') - Az adatbázis hibát jelez
- Ez a hiba hasznos információkat szivárog ki az adatbázisról (például a DB oszlopok száma szerkezetének típusa stb.)
2. Unió-alapú SQL-injekció
Az Unió-alapú SQL Injection egy olyan technika, ahol a támadók a UNION operátor két vagy több eredményének kombinálásához SELECT kijelentéseket egyetlen eredményhalmazba. Ez lehetővé teszi számukra, hogy információkat nyerjenek ki az adatbázis más tábláiból. A UNION operátor csak akkor használható, ha:
- Mindkét lekérdezésnek ugyanannyi oszlopa van
- Az oszlopok hasonló adattípusokkal rendelkeznek
- Az oszlopok ugyanabban a sorrendben vannak
UNION operátor : A UNION operátor a kettő vagy több eredményhalmaz kombinálására szolgál SELECT nyilatkozatok.
- Minden
SELECTnyilatkozat belülUNIONugyanannyi oszlopnak kell lennie - Az oszlopoknak hasonló adattípusokkal kell rendelkezniük
- Az oszlopoknak ugyanabban a sorrendben kell lenniük
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2Példa:
1. lépés: Először is meg kell találnunk a webhelyen lévő meglévő tábla oszlopainak számát az UNION alapú SQL Injection beszúrásához:
Az SQL Injection oldalon van egy egyszerű beviteli mező, ahol megadhatja a felhasználói azonosítót. A háttérlekérdezés valószínűleg valami ilyesmi
SELECT * FROM users WHERE id = 'user_input'Most próbálja megszakítani a lekérdezést. Adjon meg egyetlen idézetet
'a beviteli mezőbe, és küldje el.Ha az alkalmazás sebezhető, részletes hibaüzenetet fog kapni. Valahogy így nézhet ki:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 12. lépés: Használja a
UNIONKulcsszó az oszlopok számának felfedezéséhezHasználatához a
UNIONkulcsszó (egy gyakori következő lépés), ismernie kell az eredeti lekérdezés oszlopainak számát. Ezt a segítségével megtudhatjaORDER BYzáradék
- Próbálja meg az eredményeket oszlopok szerint rendezni
1:1 ORDER BY 1.
- Beküld. Működnie kell.
SQL befecskendezési forrás
PHP if ( isset ( $_REQUEST [ 'Submit' ] ) ) { // Get input $id = $_REQUEST [ 'id' ]; switch ( $_DVWA [ 'SQLI_DB' ]) { case MYSQL : // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = ' $id ';' ; $result = mysqli_query ( $GLOBALS [ '___mysqli_ston' ] $query ) or die ( ' '
. (( is_object ( $GLOBALS [ '___mysqli_ston' ])) ? mysqli_error ( $GLOBALS [ '___mysqli_ston' ]) : (( $___mysqli_res = mysqli_connect_error ()) ? $___mysqli_res : false )) . '
' ); // Get results while ( $row = mysqli_fetch_assoc ( $result ) ) { // Get values $first = $row [ 'first_name' ]; $last = $row [ 'last_name' ]; // Feedback for end user echo ' ID:
{ $id }
First name: { $first }
Surname: { $last } ' ; } mysqli_close ( $GLOBALS [ '___mysqli_ston' ]); break ; case SQLITE : global $sqlite_db_connection ; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = ' $id ';' ; #print $query; try { $results = $sqlite_db_connection -> query ( $query ); } catch ( Exception $e ) { echo 'Caught exception: ' . $e -> getMessage (); exit (); } if ( $results ) { while ( $row = $results -> fetchArray ()) { // Get values $first = $row [ 'first_name' ]; $last = $row [ 'last_name' ]; // Feedback for end user echo ' ID:
{ $id }
First name: { $first }
Surname: { $last } ' ; } } else { echo 'Error in fetch ' . $sqlite_db -> lastErrorMsg (); } break ; } } ?> - Növelje a számot:
1 ORDER BY 2.Beküld. Működnie kell.
![]()
- Folytassa a növelést, amíg hibaüzenetet nem kap. Például
1 ORDER BY 4adhat neked:Unknown column '4' in 'order clause' - Ez azt jelenti, hogy a lekérdezésnek 3 oszlopa van.
3. Blind-Based SQL Injection
Vak SQL-injekció akkor fordul elő, ha a támadók nem látják közvetlenül a weboldalon a lekérdezés eredményeit. Ehelyett az alkalmazás viselkedésének vagy válaszidejének finom változásaiból következtetnek az információkra. Bár lassabb és fárasztóbb, mint a klasszikus SQLi, ugyanolyan hatékony lehet.
Az adatok visszaszerzése helyett a támadó a weboldal viselkedésének megfigyelésével következtet információkra. Ez általában kétféle módon történik:
- Logikai alapú vak SQLi: A támadó bead egy SQL-lekérdezést, amely a igaz vagy hamis eredmény. A webalkalmazás válasza attól függően változik, hogy a lekérdezés igaz vagy hamis. Például az oldal más üzenetet jeleníthet meg, vagy más elrendezést jeleníthet meg.
- Időalapú vak SQLi: A támadó bead egy SQL lekérdezést, amely időigényes művelet végrehajtására készteti az adatbázist (például
SLEEP()függvény), ha egy feltétel teljesül. A támadó figyeli, hogy mennyi időbe telik az oldal betöltődése annak megállapításához, hogy a beinjektált feltétel igaz vagy hamis volt-e.
Példa:
Képzeljen el egy bejelentkezési oldalt, ahol megadja a felhasználónevet és a jelszót. Az alkalmazás a következőhöz hasonló SQL-lekérdezést készít:
SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'A vak SQL-befecskendezés a
user_inputmezőben, hogy kérdést tegyen fel az adatbázisnak.Ahelyett, hogy közvetlen választ kapna, a támadó valami ilyesmivel próbálkozhat:
user_input = 'admin' AND 1=1; --Ha az oldal normálisan betöltődik, a támadó tudja ezt
1=1az a igaz nyilatkozat.user_input = 'admin' AND 1=2; --Ha az oldal hibát jelez, vagy másként viselkedik, a támadó tudja ezt
1=2az a hamis nyilatkozat.![]()
Ezeknek az igaz/hamis kérdéseknek a használatával a támadó szisztematikusan kitalálhatja és egy-egy karakterrel információt nyerhet ki. A folyamat automatizálható, és a táblanevektől a felhasználói jelszavakig mindent kitalál.
Az SQL-injekciós támadások hatása
- Az érzékeny adatokhoz való jogosulatlan hozzáférés : A támadók lekérhetik az adatbázisban tárolt személyes pénzügyi vagy bizalmas információkat.
- Adatintegritási problémák : A támadók módosíthatják az alkalmazás működését befolyásoló kritikus adatok törlését vagy megrongálódását.
- A privilégiumok eszkalációja : A támadók megkerülhetik a hitelesítési mechanizmusokat, és rendszergazdai jogosultságokat szerezhetnek.
- Szolgáltatás leállás : Az SQL injekció túlterhelheti a kiszolgálót, ami teljesítménycsökkenést vagy rendszerösszeomlást okozhat.
- A hírnév károsodása : Egy sikeres támadás súlyosan károsíthatja a szervezet hírnevét, ami az ügyfelek bizalmának elvesztéséhez vezethet.
SQL-injekciós támadások megelőzése
Számos bevált módszer létezik az SQL injekciós támadások megelőzésére:
1. Használjon előkészített utasításokat és paraméterezett lekérdezéseket
Az előkészített utasítások és paraméterezett lekérdezések biztosítják, hogy a felhasználói bemeneteket a rendszer adatként kezelje, nem pedig az SQL-lekérdezés részeként. Ez a megközelítés kiküszöböli az SQL injekció kockázatát.
Példa PHP-ben (MySQLi használatával):
$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();2. Tárolt eljárások alkalmazása
A tárolt eljárások az adatbázisban tárolt előre meghatározott SQL lekérdezések. Ezek az eljárások segíthetnek megakadályozni az SQL-befecskendezést, mivel nem hoznak létre dinamikusan SQL-lekérdezéseket.
Példa:
CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;3. Az engedélyezési lista bevitelének ellenőrzése
Győződjön meg arról, hogy a felhasználói bemenetek érvényesek, mielőtt SQL-lekérdezésekben használnák őket. Csak bizonyos karakterek és minták, például alfanumerikus bevitel engedélyezése olyan mezőkben, mint a felhasználónevek vagy az e-mail címek.
4. Használja az ORM-keretrendszereket
Object-Relational Mapping (ORM) keretrendszerek, mint pl Hibernálni vagy Entitás-keretrendszer segíthet megakadályozni az SQL-befecskendezést azáltal, hogy automatikusan kezeli a lekérdezésgenerálást, megakadályozva a dinamikus lekérdezések felépítését.
5. Az adatbázis-jogosultságok korlátozása
Adja meg a minimálisan szükséges adatbázis-engedélyeket a felhasználóknak. Győződjön meg arról, hogy az alkalmazások csak a szükséges műveleteket hajthatják végre (pl. SELECT INSERT), és korlátozza az engedélyeket, például a DROP TABLE vagy az ALTER engedélyeket.
6. Hibakezelés
Állítsa be az adatbázist és az alkalmazást úgy, hogy ne jelenítsen meg részletes hibaüzeneteket a felhasználónak. Ehelyett belsőleg naplózza a hibákat, és általános hibaüzeneteket jelenít meg a végfelhasználók számára.