Red Kit

WFN Üye
Konular
580
Mesajlar
580
Çözüm
0
Ticaret Puanı
0
Üyelik
23 Gün
Konum
Adana
Web Sitesi
Var
Alanı
Makale Yazarı
1/1
Konu sahibi
SQL injection saldırılarını önlemenin temel yolu, kullanıcıdan gelen değerleri SQL metnine birleştirmemek ve veritabanı sürücüsünün desteklediği parametreli sorguları kullanmaktır. Bunun yanında tablo ve sütun adları gibi sorgu yapısının parçalarını yalnızca izin verilen sabit seçeneklerden seçmeli, uygulama hesabına gereksiz veritabanı yetkileri vermemeli ve girişleri beklenen veri türüne göre doğrulamalısınız. Bu önlemler birlikte uygulandığında saldırganın gönderdiği metin, çalıştırılacak SQL komutu yerine yalnızca veri olarak değerlendirilir.

Kullanıcı girdisi sorguya nasıl eklenmemeli?​


Aşağıdaki yaklaşım tehlikelidir; çünkü $email değişkeni doğrudan SQL metnine eklenmektedir:

PHP:
$email = $_POST['email'];
$sql = "SELECT id, name FROM users WHERE email = '$email'";
$result = $pdo->query($sql);

Kullanıcı girdisi, sorgunun tırnaklarını veya yapısını değiştirirse veritabanı uygulamanın amaçladığından farklı bir komut çalıştırabilir. Girdinin formdan, çerezden, gizli alandan veya açılır listeden gelmesi bunu güvenli hâle getirmez; istemciden gelen her değer güvenilmeyen veri olarak ele alınmalıdır.

Parametreli sorguya geçiş​


Örneğin kullanıcı e-postasına göre kayıt arayan PHP ve PDO kodunda sorgu şablonunu değerlerden ayırın:

PHP:
$email = $_POST['email'] ?? '';

$sql = 'SELECT id, name FROM users WHERE email = :email';
$stmt = $pdo->prepare($sql);
$stmt->execute(['email' => $email]);

$user = $stmt->fetch(PDO::FETCH_ASSOC);

Burada :email bir yer tutucudur. E-postanın gerçek değeri SQL metnine birleştirilmez; execute() sırasında ayrı parametre olarak gönderilir. Kullanıcı ' OR '1'='1 gibi bir metin gönderse bile bu değer, sorgunun koşulunu değiştiren SQL parçası değil, aranacak tek bir veri değeri olarak işlenmelidir.

Kodunuzda prepare() kullanıp kullanıcı değerini yine de sorgu metninin içine yazarsanız koruma sağlamış olmazsınız. Her dinamik değer için ayrı bir yer tutucu kullanın ve değerleri execute(), bindValue() veya kullandığınız kütüphanenin eşdeğer parametre bağlama yöntemiyle gönderin.

Arama, ekleme, güncelleme ve silme sorguları​


Aynı kural bütün sorgu türleri için geçerlidir. Örneğin kayıt eklerken:

PHP:
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';

$stmt = $pdo->prepare(
    'INSERT INTO users (name, email) VALUES (:name, :email)'
);
$stmt->execute([
    'name' => $name,
    'email' => $email,
]);

Sorgu başarıyla çalışırsa yeni kayıt eklenir; hata oluşursa uygulamanın ayrıntılı veritabanı hatasını ziyaretçiye göstermeyin. Hatayı sunucu tarafında günlükleyin, kullanıcıya ise işlemin başarısız olduğunu belirten genel bir yanıt verin. Günlüklerde parola, oturum belirteci veya gereksiz kişisel veri bırakmayın.

Tablo ve sütun adları için farklı yöntem gerekir​


Parametreler veri değerlerini temsil eder; tablo adı, sütun adı, SQL anahtar sözcüğü veya sorgunun keyfî bir bölümü yerine kullanılamaz. Bu nedenle sıralama alanını doğrudan istekten alıp sorguya eklemek güvenli değildir:

PHP:
$sort = $_GET['sort'] ?? 'name';
$sql = "SELECT id, name, email FROM users ORDER BY $sort";

Bunun yerine dışarıdan gelen seçeneği sabit bir izin listesinde eşleyin:

PHP:
$sortInput = $_GET['sort'] ?? 'name';
$allowedSorts = [
    'name' => 'name',
    'newest' => 'created_at',
];

$sortColumn = $allowedSorts[$sortInput] ?? 'name';

$stmt = $pdo->query(
    "SELECT id, name, email FROM users ORDER BY $sortColumn"
);

Burada sorguya eklenen değer, kullanıcının gönderdiği ham metin değil, uygulamada önceden tanımlanmış sütun adlarından biridir. Sıralama yönü gibi seçeneklerde de aynı yaklaşımı kullanın: yalnızca ASC veya DESC gibi izin verilen değerlerden birini seçin. İzin listesi yoksa ilgili özelliği kullanıcı girdisiyle dinamik hâle getirmeyin.
Sorgu bölümüGüvenli yaklaşım
Değerler: arama metni, e-posta, kimlikParametreli sorgu ve bağlı değer
Tablo veya sütun adıSabit seçim ya da izin listesi eşlemesi
Sıralama yönüÖnceden belirlenmiş ASC/DESC seçenekleri
Sayısal kimlikBeklenen veri türü doğrulaması ve parametreli sorgu
Bu ayrım önemlidir: Parametreli sorgu, veri değerlerinin SQL komutuna dönüşmesini engeller; yanlış seçilmiş bir tablo adı veya sütun adı için tek başına çözüm değildir.

Girdi doğrulama ve veritabanı yetkileri​


Parametreli sorgu ana savunmadır; doğrulama ise uygulamanın beklenmeyen verilerle çalışmasını önleyen ek katmandır. Kimlik alanı bekleniyorsa gerçekten izin verilen biçimde bir kimlik alın, sayısal olmayan değeri işlemden önce reddedin. E-posta alanında biçim kontrolü yapın; ancak biçim kontrolünü SQL injection korumasının yerine koymayın. Geçerli görünen bir değer de sorguya doğrudan birleştirilirse risk devam eder.

Uygulama veritabanına yönetici veya veritabanı sahibi hesabıyla bağlanmamalıdır. Kullanılan hesap yalnızca uygulamanın ihtiyaç duyduğu tablo ve işlemlere erişebilmelidir. Böylece bir sorgu açığı oluşsa bile saldırganın etkileyebileceği alan daralır. Bu, açığı ortadan kaldırmaz; yalnızca ek zarar sınırlaması sağlar.

Mevcut kod nasıl denetlenir?​


Önce uygulamanın veritabanına eriştiği tüm dosya ve sınıfları çıkarın. Özellikle query(), exec(), mysqli_query(), SQL birleştirme işlemleri ve değişken içeren sorgu dizelerini arayın. Her bulguda şu sırayı izleyin:
  1. Sorguya giren değerin kaynağını belirleyin: form, URL, çerez, başlık, dosya veya başka bir servis.
  2. Değer SQL metnine birleştiriliyorsa sorguyu sabit şablon ve parametreler kullanacak şekilde yeniden yazın.
  3. Tablo, sütun veya sıralama gibi yapısal bir bölüm dinamikse ham değeri kaldırıp izin listesi eşlemesi ekleyin.
  4. Bağlanan veritabanı hesabının gerçekten ihtiyaç duyduğu yetkileri kontrol edin.
  5. Değişiklikten sonra normal geçerli girdilerle ve reddedilmesi gereken hatalı girdilerle uygulamanın beklenen davranışını sınayın.
Normal arama sonucunun dönmesi, SQL injection açığının kesin olarak bulunmadığını kanıtlamaz; yalnızca o girdinin uygulamayı bozmadığını gösterir. Veritabanı hata mesajı alınması da tek başına açık kanıtı değildir, ancak sorgu yapısının dış girdiden etkilenebildiğine işaret edebilir. Kod incelemesinde kullanıcı değerinin SQL metnine girip girmediği ve parametre olarak bağlanıp bağlanmadığı esas kontroldür.

Bir test sırasında uygulamanın gerçek verilerini değiştirmeyin veya silmeyin. Üretim ortamında saldırı dizeleri denemek yerine izole bir kopya, test veritabanı ve yedek kullanın. Şüpheli bir açıklık bulunursa ilgili uç noktanın adresini, etkilenen parametreyi, uygulama ve veritabanı sürümünü, hata zamanını ve sunucu günlüklerindeki ilgili kayıtları güvenli biçimde saklayın; parolaları ve oturum bilgilerini paylaşmadan düzeltme talebi oluşturun. Açık kapatıldıktan sonra aynı kod yolunun bütün sorgu türlerinde parametreli çalıştığını yeniden inceleyin.
 

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Foruma git ?

Bu konuyu görüntüleyen kullanıcılar

Bu konuyu şu anda görüntüleyen üye bulunmuyor.
Robotlar:
  • Anthropic