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.

Reklam · TEST
AdSense Test ReklamıYazı arası (gönderi içi) · Yazı arası
1import sqlite3
2
3conn = sqlite3.connect('users.db')
4cursor = conn.cursor()
5
6username = input("Kullanıcı adı: ")
7password = input("Şifre: ")
8
9# Güvenli sorgu
10query = "SELECT * FROM users WHERE username =? AND password =?"
11cursor.execute(query, (username, password))
12
13result = cursor.fetchone()
14
15if result:
16print(f"Hoş geldiniz, {result[0]}!")
17else:
18print("Giriş başarısız.")
19
20conn.close()

Çıktı (başarılı giriş):

1Kullanıcı adı: ali
2Şifre: 12345
3Hoş 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'];
3
4$conn = new mysqli("localhost", "user", "pass", "mydb");
5
6$stmt = $conn->prepare("SELECT * FROM users WHERE username =? AND password =?");
7$stmt->bind_param("ss", $username, $password);
8$stmt->execute();
9
10$result = $stmt->get_result();
11
12if ($result->num_rows > 0) {
13echo "Giriş başarılı.";
14} else {
15echo "Hatalı bilgiler.";
16}
17
18$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.

Reklam · TEST
AdSense Test ReklamıGönderi altı · Görüntülü
konu hakkında tepkinizi verebilirsiniz