SQL Injection'dan Koruma: Prepared Statements Rehberi
SQL Injection, saldırganın kötü amaçlı SQL kodunu kullanıcı girdisine gömerek veritabanını manipüle etmesi demek. Örneğin bir login formuna `' OR '1'='1` yazarsa, şifre kontrolü atlatabilir. Bunu önlemenin en güvenilir yolu Prepared Statements (hazırlanmış sorgular) kullanmaktır.
Geleneksel sorgu yazımında giriş doğrudan SQL cümlesine birleştirilir:
1username = request.form['username']2query = "SELECT * FROM users WHERE username = '" + username + "'"Eğer kullanıcı `admin' --` yazarsa, sorgu şu hale gelir:
1SELECT * FROM users WHERE username = 'admin' --'Yorum işareti (`--`) sonrasındaki şifre kontrolü yok sayılır ve hesaba giriş yapılır.
Prepared Statements, SQL sorgusunu iki aşamada işler:
1. Hazırlama: SQL yapısı veritabanına gönderilir, parametreler boş kalır.
2. Bağlama: Kullanıcı verileri güvenli şekilde parametrelere atanır.
Bu yöntemde SQL kodu ve veri kesinlikle ayrı kalır.
1import sqlite323conn = sqlite3.connect('users.db')4cursor = conn.cursor()56username = input("Kullanıcı adı: ")7password = input("Şifre: ")89# Güvenli sorgu10query = "SELECT * FROM users WHERE username =? AND password =?"11cursor.execute(query, (username, password))1213result = cursor.fetchone()1415if result:16print(f"Hoş geldiniz, {result[0]}!")17else:18print("Giriş başarısız.")1920conn.close()Çıktı (başarılı giriş):
1Kullanıcı adı: ali2Şifre: 123453Hoş geldiniz, ali!Eğer saldırgan `admin' --` yazsa bile, sistem bunu literal metin olarak arar ve bulamaz.
1$username = $_POST['username'];2$password = $_POST['password'];34$conn = new mysqli("localhost", "user", "pass", "mydb");56$stmt = $conn->prepare("SELECT * FROM users WHERE username =? AND password =?");7$stmt->bind_param("ss", $username, $password);8$stmt->execute();910$result = $stmt->get_result();1112if ($result->num_rows > 0) {13echo "Giriş başarılı.";14} else {15echo "Hatalı bilgiler.";16}1718$stmt->close();19$conn->close();`bind_param()` parametreleri güvenli şekilde bağlar. İlk argüman (`"ss"`) veri türünü gösterir: `s` = string, `i` = integer.
- Saldırganın SQL sözdizimini değiştirmesi imkânsız hale gelir.
- Veri ve kod tamamen ayrıştırılır.
- Veritabanı yönetim sistemi tarafından doğrudan desteklenir.
- Performans avantajı da sağlar (sorgu bir kez derlenir).
Her zaman Prepared Statements kullan. String birleştirme veya format işlevleri hiçbir zaman yeterli değildir.
0 yorum