Kapcsolódó bejegyzések
-
- The Year in Computer Science
- Az Elmúlt Évtized 10 Technológiai Csodája: Hardver és Szoftver Újdonságok, Amik Megváltoztatták Az Életünket
- A Számítógép Memóriák Forradalmi Fejlődése: Az UltraRAM Technológia
- Mesterséges Intelligencia Fejlődésének Új Korszaka és Az Emberekre Váró Új Kihívások
- Titkos Őrzők: Hatékony Módszerek a Személyes Adatok Védelmére az Online Világban!
💥 Az SQL Injection – Amikor a weboldalad saját magát árulja el
🔍 Bevezető: amikor a felhasználói adat parancsként fut le
Képzeld el, hogy készítettél egy egyszerű bejelentkezési űrlapot egy weboldalon: a felhasználó megadja a nevét és jelszavát, a háttérben pedig az alkalmazás lekérdezi az adatbázist, hogy van-e ilyen felhasználó.
Teljesen ártatlannak tűnik.
Például egy tipikus lekérdezés így nézhet ki SQL-ben:
SELECT * FROM users WHERE username = 'geza' AND password = 'titok123'
Ez azt mondja az adatbázisnak:
„Add vissza azt a felhasználót, akinek username = geza és password = titok123.”
Most képzeld el, hogy valaki nem „geza”-t ír be, hanem ezt:
Felhasználónév: ‘ OR 1=1 —
Jelszó: akármi
Így a lekérdezés ez lesz:
SELECT * FROM users WHERE username = '' OR 1=1 --' AND password = 'akármi'
Amit az adatbázis így értelmez:
- username = ” – Ez hamis (üres felhasználónév nincs).
- OR 1=1 – Ez mindig igaz.
- — – Ez egy SQL megjegyzés jelölő, ami elvágja a lekérdezés többi részét (a jelszót is).
Így az egész WHERE rész gyakorlatilag így néz ki:
WHERE TRUE
Azaz az adatbázis minden sort visszaad, és az elsőt (pl. admin) felhasználva a támadó be van léptetve.
💡 A lényeg: az SQL nem „látja”, hogy ez felhasználói adat
A hagyományos SQL-lekérdezés nem különbözteti meg a programkódból származó részt és a felhasználótól érkező adatot – mindkettőt ugyanúgy kezeli. Ha tehát a felhasználó adatában SQL parancs van, az parancsként fog lefutni.
Ez az SQL Injection: amikor a felhasználó adatnak álcázva utasítást ad az adatbázisnak
⚠️ Valós példák – amikor ez nem csak elmélet
- 🔐 2008 – Heartland Payment Systems
Több százmillió hitelkártya-adat került ki az egyik legnagyobb amerikai kártyafeldolgozótól. Az egyik behatolási pont egy klasszikus SQL Injection volt.
- 🏦 2012 – LinkedIn (és mások)
SQLi segítségével szerezték meg a jelszóhash-eket.
A támadók később több másik platformra is beléptek, ahol a felhasználók ugyanazt a jelszót használták.
- 🛍️ 2017 – eBay szivárgás
A nyilvános API-k egyikén SQLi támadással lekérdezhetők voltak más felhasználók adatai – bizonyos feltételek mellett.
Az OWASP szerint az SQL Injection évtizedek óta a TOP 10 legveszélyesebb webes sebezhetőség között szerepel.
🧪 Interaktív példa: sebezhető Python GUI
Ha szeretnéd saját szemeddel látni, milyen egyszerű kihasználni egy ilyen hibát, próbáld ki az alábbi Python programot:
🔓 Sebezhető verzió (NE HASZNÁLD ÉLESBEN!)
import tkinter as tk from tkinter import messagebox import sqlite3 conn = sqlite3.connect(":memory:") c = conn.cursor() c.execute("CREATE TABLE users (username TEXT, password TEXT)") c.execute("INSERT INTO users VALUES ('admin', 'admin123')") conn.commit() def login(): username = entry_username.get() password = entry_password.get() query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'" print("[LEKÉRDEZÉS]:", query) c.execute(query) result = c.fetchone() if result: messagebox.showinfo("Siker", "✅ Sikeres bejelentkezés!") else: messagebox.showerror("Hiba", "❌ Hibás adatok!") root = tk.Tk() tk.Label(root, text="Felhasználónév:").pack() entry_username = tk.Entry(root); entry_username.pack() tk.Label(root, text="Jelszó:").pack() entry_password = tk.Entry(root, show="*"); entry_password.pack() tk.Button(root, text="Bejelentkezés", command=login).pack() root.mainloop()
🚨 Támadás bemenet:
- Felhasználónév: ‘ OR 1=1 —
- Jelszó: bármi
Ez automatikusan beléptet, mert a lekérdezés minden felhasználóra igaz lesz.
🛡️ A megoldás: paraméterezett lekérdezések
A probléma gyökere, hogy a felhasználó inputja lekérdezésként értelmeződik, nem adatként.
Ezt úgy lehet elkerülni, ha paraméterezett lekérdezést használsz:
✅ Biztonságos verzió:
query = "SELECT * FROM users WHERE username = ? AND password = ?" c.execute(query, (username, password))
Itt az SQLite (vagy bármely adatbázis-kezelő) már tudja, hogy a ? helyére csak érték kerülhet, nem utasítás.
Ugyanez más nyelvekben:
- PHP (PDO):
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
$stmt->execute([$username, $password]);
- Java (JDBC):
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE username = ? AND password = ?"); stmt.setString(1, username); stmt.setString(2, password);
🧰 További védekezési technikák
- Használj ORM-et (pl. SQLAlchemy, Django ORM, Laravel Eloquent).
- Validáld a bemenetet (különösen azonosítók, számok, sémák).
- Soha ne adj direkt SQL hozzáférést frontendnek!
- Használj tesztelő eszközöket (pl. OWASP ZAP, sqlmap).
- Használj minimális adatbázis-jogosultságot.
👨🏫 Zárás: tanítsd, használd, figyelj
Az SQL Injection kivédése nem nehéz, de felelősségteljes fejlesztést igényel.
Sok modern keretrendszer már eleve védi a fejlesztőt, de a régi kódok, egyedi projektek és gyorstákolt megoldások gyakran még mindig nyitva hagyják a kaput.
Ha webfejlesztéssel foglalkozol, ezt a hibát ismerned kell. Ha oktatsz, mutasd meg diákjaidnak élőben. És ha rendszert építesz, teszteld le a saját megoldásaidat is.
Mert lehet, hogy valaki egyszer megpróbál beírni egy ‘ OR 1=1 — sort — és akkor már késő lesz.