Skip to content
Language:hu Author:Laborci Gergely
web-security

Injekció: amikor az adatból utasítás lesz

Célok

A lecke végére el tudod magyarázni az injekció lényegét (a kód és az adat összekeveredése), le tudod olvasni egy SQL-injekció működését, és tudod, miért paraméterezett lekérdezés a fő védelem.

Miért veszélyes az összefűzött lekérdezés?

A Kurzuspont kurzuskereső funkciója az adatbázisból kérdezi le a kurzust az azonosítója alapján. Ha a szerver a kapott azonosítót szövegként egy SQL-lekérdezésbe (SQL: Structured Query Language, a relációs adatbázisok lekérdezőnyelve) fűzi, a bemenet a lekérdezés szintaxisának részévé válhat. A támadó ekkor nem adatot ad, hanem utasítást adatként becsomagolva. Az injekció (injection) lényege tehát nem a furcsa karakter, hanem a kód és az adat összekeverése. Ugyanez az elv fennáll más értelmezőknél is: parancsértelmező, sablonmotor. Az OWASP Top 10:2025 listán az injekció az 5. kategória (A05).

Kipróbálva: összefűzött és paraméterezett lekérdezés

Egy kis adatbázis három kurzussal: kettő nyilvános (nyilvanos = 1), egy belső, nem nyilvános. A kereső a nyilvános kurzusokat adja vissza az azonosító szerint. Ugyanazt a bemenetet két módon adtuk át az SQLite adatbázisnak (Node.js 24, beépített node:sqlite modul):

// ÖSSZEFŰZÖTT (veszélyes):
const naiv = `SELECT id, cim FROM kurzus WHERE nyilvanos = 1 AND id = '${bemenet}'`;
// PARAMÉTEREZETT (biztonságos):
const par = db.prepare('SELECT id, cim FROM kurzus WHERE nyilvanos = 1 AND id = ?');
par.all(bemenet);

1. Normál bemenet: webprog

SQL (összefűzött): SELECT id, cim FROM kurzus WHERE nyilvanos = 1 AND id = 'webprog'
-> [{"id":"webprog","cim":"Webprogramozás 1."}]
SQL (paraméterezett): ... id = ?   [paraméter: "webprog"]
-> [{"id":"webprog","cim":"Webprogramozás 1."}]

Mindkét változat helyesen működik.

2. Támadó bemenet: x' OR '1'='1

SQL (összefűzött): SELECT id, cim FROM kurzus WHERE nyilvanos = 1 AND id = 'x' OR '1'='1'
-> [{"id":"webprog",...},{"id":"adatbazisok",...},{"id":"belso","cim":"Belső oktatói értekezlet"}]
SQL (paraméterezett): ... id = ?   [paraméter: "x' OR '1'='1"]
-> []

Az összefűzött változatban a bemenet idézőjele lezárta a szöveget, az OR '1'='1' pedig új feltételt adott, amely mindig igaz. Mivel az AND erősebben köt, mint az OR, a nyilvanos = 1 megszorítás hatástalan lett, és a belső értekezlet is megjelent. A paraméterezett változatban a teljes bemenet egyetlen szöveges érték maradt: ilyen azonosítójú kurzus nincs, ezért a válasz üres.

3. Még célzottabb bemenet: x' OR nyilvanos = 0 --

SQL (összefűzött): SELECT id, cim FROM kurzus WHERE nyilvanos = 1 AND id = 'x' OR nyilvanos = 0 --'
-> [{"id":"belso","cim":"Belső oktatói értekezlet"}]
SQL (paraméterezett): ... id = ?   [paraméter: "x' OR nyilvanos = 0 --"]
-> []

A -- az SQL-ben megjegyzést kezd, így a támadó a lekérdezés hátralévő részét is eltüntette. Itt kifejezetten a belső kurzust kapta meg.

flowchart LR
    V[Felhasználói érték] --> P[Paraméter]
    Q[Állandó SQL-szerkezet] --> E[Adatbázismotor]
    P --> E
    E --> R[Adatként értelmezett érték]

Miért működik a paraméterezés?

A paraméterezett lekérdezésnél (prepared statement) az SQL-szerkezet és a felhasználói érték külön jut az adatbázishoz. Az adatbázis előbb értelmezi a lekérdezés szerkezetét (... id = ?), és a paraméter csak ezután kerül a helyére értékként, soha nem utasításként. Az OWASP SQL-injekció elleni útmutatója szerint ez az elsődleges védelem: az adatbázis a bemenetet adatként kezeli, nem kódként.

Az útmutató a következő sorrendet adja:

  1. Paraméterezett lekérdezés (prepared statement).
  2. Tárolt eljárások, ha biztonságosan (paraméterekkel, nem dinamikus SQL-lel) készültek.
  3. Engedélyezőlistás bemenet-ellenőrzés ott, ahol paraméter nem használható (például tábla- vagy oszlopnév, rendezési irány): a felhasználói értéket ismert, jó értékekre kell leképezni.
  4. Karakterek escape-elése: az útmutató ezt erősen ellenzi, mert törékeny, és nem garantál védelmet.

Kiegészítő védelem a legkisebb jogosultság elve: az alkalmazás adatbázis-fiókja csak azt tehesse meg, amire szüksége van (ne legyen adminisztrátori fiók), és alkalmazásonként külön adatbázis-felhasználó legyen. Így egy hiba kisebb kárt okoz.

Más értelmezők, ugyanaz a gondolat

Az injekció akkor jön létre, ha a program olyan szöveget épít, amelyet egy másik értelmező utasításként olvas: SQL-motor, operációs rendszer parancssora, sablonmotor, keresőszolgáltatás lekérdezőnyelve. A védelem mindig ugyanaz az elv: az utasítás szerkezete és a felhasználói érték külön csatornán jusson el az értelmezőhöz, vagy az értéket az adott értelmező szabályai szerint kell biztonságosan kezelni. Az XSS (8.3) rokon gondolat: ott az értelmező a böngésző HTML-elemzője.

Végigvezetett példa: a Kurzuspont kurzuskeresője

Lépés Döntés
A kereső lekérdezése Paraméterezett lekérdezés, az azonosító csak értékként kerül be.
Rendezési irány a felületről (ASC/DESC) Engedélyezőlista: csak ez a két érték mehet be a lekérdezésbe.
Az alkalmazás adatbázis-fiókja Csak olvasás a kurzus táblán; a belső táblákhoz nincs joga.
A belső kurzus (nyilvanos = 0) A szabályt a lekérdezés és a jogosultsági réteg is érvényesíti (7.4).

Így még egy hibás kód sem adná ki a belső kurzusokat.

Gyakori tévhitek

Állítás Pontosítás
„Elég minden különleges karaktert törölni.” A helyes kezelés az értelmezési környezettől függ; SQL-nél paraméterezés kell.
„Az ORM (Object-Relational Mapping, objektum-relációs leképezés) automatikusan megvéd.” Csak akkor, ha paraméterezett lekérdezést használ; nyers SQL-összefűzésnél nem.
„A bemenet-ellenőrzés elég.” Az üzleti szabályokhoz hasznos, de a paraméterezés nem helyettesíthető vele.
„Az injekció csak SQL-nél létezik.” Bármely értelmezőnél előfordulhat.
„A HTTPS véd az injekció ellen.” A támadó adata titkosított csatornán is eljut a szerverhez (4.3).

Röviden

  • Az injekció a kód és az adat összekeveredése: a bemenet utasításként értelmeződik.
  • A kipróbált összefűzött SQL a támadó bemenetére kiadta a belső kurzust; a paraméterezett lekérdezés nem.
  • Fő védelem: paraméterezett lekérdezés; engedélyezőlista a nem paraméterezhető részeken; escape-elni nem szabad megoldásként.
  • Kiegészítés: legkisebb jogosultság az adatbázis-fiókon.

Ellenőrző kérdések

  1. Miért tette láthatóvá a belső kurzust az x' OR '1'='1 bemenet?
  2. Miben más a paraméterezett lekérdezés az összefűzöttnél?
  3. Miért nem jó megoldás a speciális karakterek törlése vagy escape-elése?
  4. Mikor kell engedélyezőlistát használni a paraméterezés helyett?

Tanulási források

Prerequisites (1)

  • HTTP

Teaches (2)

  • injekció
  • paraméterezett lekérdezés