# SQL Enjeksiyonu ve Veri Tabanı Güvenliği

> SQL enjeksiyonu, güvenilmeyen girdinin sorguya veri olarak değil yürütülebilir SQL sözdizimi olarak katılmasıyla oluşur.

- Author: Muhammet Ali Köker
- Language: tr
- Canonical: https://alikoker.com.tr/sql-enjeksiyonu
- Translation: https://alikoker.com.tr/en/sql-injection-and-database-security
- Published: 2021-07-02T17:48:27+03:00
- Modified: 2026-08-31T22:45:00+03:00
- Verified: 2026-08-07T11:00:00+03:00
- Type: article

SQL enjeksiyonu, güvenilmeyen girdinin SQL komut yapısına veri olarak değil yürütülebilir sözdizimi olarak katılmasıdır. Açık yalnız web formlarında görülmez; masaüstü istemcileri, mobil uygulamalar, raporlama araçları, komut satırı uygulamaları ve arka plan görevleri de aynı hatayı üretebilir.

SQL enjeksiyonu, güvenilmeyen girdinin veri olarak kalmayıp veri tabanı komutunun yapısını değiştirebilmesiyle ortaya çıkar. Web, masaüstü ve mobil veri erişim katmanlarında aynı temel hata görülür; savunmanın çekirdeğini parametreli sorgular, en az ayrıcalık, kontrollü hata yönetimi ve yeterli gözlemlenebilirlik oluşturur.

## Açığın Oluşum Koşulu

Temel hata, kullanıcı girdisi ile SQL sözdiziminin string birleştirme üzerinden aynı metinde oluşturulmasıdır:

```csharp
string sql = "SELECT id FROM users WHERE username='" + username + "' AND password='" + password + "'";
```

Bu yapıda tırnak, yorum veya operatör içeren girdi sorgunun yapısını değiştirebilir. Girdide belirli karakterleri yasaklamak kalıcı çözüm değildir. Kodlama biçimleri, alternatif sözdizimleri, veri tabanı farklılıkları ve ikinci aşama enjeksiyonları filtreyi aşabilir.

## Parametreli Sorgu

SQL komutu ile değerler ayrı kanallardan gönderilmelidir:

```csharp
const string sql = "SELECT id FROM users WHERE username = @username AND password_hash = @passwordHash";
using SqlCommand command = new SqlCommand(sql, connection);
command.Parameters.Add("@username", SqlDbType.NVarChar, 128).Value = username;
command.Parameters.Add("@passwordHash", SqlDbType.VarBinary, 32).Value = passwordHash;
```

Parametre yalnız değeri korur. Tablo adı, sütun adı, sıralama yönü veya SQL anahtar sözcüğü parametre olarak bağlanamaz. Bu tür dinamik parçalar sabit allowlist üzerinden seçilmelidir:

```csharp
string orderBy = sortKey switch
{
    "date" => "published_at",
    "title" => "title",
    _ => "id"
};
```

## Stored Procedure ve ORM Sınırı

Stored procedure kullanmak tek başına güvenlik sağlamaz. Procedure içinde kullanıcı girdisiyle dinamik SQL birleştiriliyorsa açık devam eder. [ORM](/wiki/object-relational-mapping) veya query builder da ham SQL, string interpolation veya yanlış dinamik filtre kullanıldığında enjeksiyon üretebilir.

Güvenli ölçüt kullanılan framework değil, veri ile komut yapısının ayrılmasıdır. Kod incelemesinde bütün SQL üretim yolları, raw query çağrıları, migration araçları ve rapor sorguları aynı tehdit modeliyle değerlendirilmelidir.

## Parola Doğrulama

Parola doğrudan SQL sorgusunda veya geri döndürülebilir biçimde tutulmamalıdır. Argon2id, scrypt veya uygun maliyet parametreli bcrypt/PBKDF2 gibi parola türetme işlevleri kullanılmalı; her parola için benzersiz salt üretilmelidir. Uygulama önce kullanıcı kaydını parametreli sorguyla almalı, ardından parola türetme sonucunu sabit zamanlı karşılaştırmaya uygun kütüphane çağrısıyla doğrulamalıdır.

Tek başına hızlı bir SHA-256 özeti parola saklama yöntemi değildir. Hızlı hash işlevleri çevrim dışı parola tahminini ucuzlatır.

## Yetki Minimizasyonu

Uygulama hesabı yalnız ihtiyaç duyduğu şema ve işlemlere erişmelidir. Okuma yapan servis hesabına tablo oluşturma, kullanıcı yönetimi veya bütün şemalara yazma yetkisi verilmemelidir. Farklı güven sınırları için ayrı hesaplar kullanılabilir.

Enjeksiyon açığı tamamen önlenemese bile asgari yetki saldırının etkisini sınırlar. Buna karşılık yalnız yetki minimizasyonuna güvenmek doğru değildir; gizli verilerin okunması veya mevcut yetki kapsamında veri değiştirilmesi yine mümkün olabilir.

## İkinci Aşama ve Saklanan Girdi

Girdi ilk kaydedildiği anda SQL yapısına katılmayabilir. Daha sonra yönetim aracı, rapor veya migration kodu bu değeri dinamik SQL içinde birleştirirse ikinci aşama enjeksiyonu oluşur. Bu nedenle veri tabanından okunmuş metin otomatik olarak güvenilir kabul edilmemelidir.

## Doğrulama ve Kodlama

Girdi doğrulama, parametreli sorgunun yerine geçmez; iş kuralını korur. Kimlik alanının pozitif tamsayı, dil kodunun sınırlı bir küme veya sayfa boyutunun belirli aralıkta olması doğrulanmalıdır.

HTML çıktısında SQL güvenliği değil, bağlama uygun çıktı kodlama gerekir. SQL parametresi XSS açığını; HTML kodlama da SQL enjeksiyonunu önlemez. Her güven sınırı kendi bağlamında ele alınmalıdır.

## Hata Mesajları ve Loglama

İstemciye SQL metni, tablo adı, sürücü stack trace veya bağlantı bilgisi gönderilmemelidir. Sunucu logları tanılama için hata sınıfı ve correlation ID içerebilir; parola, token, kişisel veri ve tam sorgu parametreleri loglanmamalıdır.

Saldırı tespiti için yalnız tekil özel karakter aranması yetersizdir. Olağandışı hata oranı, reddedilen doğrulama, beklenmeyen sorgu hacmi ve veri erişim örüntüleri birlikte izlenmelidir.

## Test Yaklaşımı

Güvenlik testi aşağıdaki katmanları kapsamalıdır:

- [Statik analiz](/wiki/static-analysis) ve kod incelemesi
- Parametreli sorgu doğrulaması
- Dinamik tanımlayıcı allowlist testleri
- Stored procedure içindeki dinamik SQL incelemesi
- Yetki matrisi testi
- Hata mesajı ve log sızıntısı kontrolü
- İkinci aşama enjeksiyon senaryoları

SQL enjeksiyonuna karşı temel savunma, güvenilmeyen veriyi SQL sözdiziminden yapısal olarak ayırmaktır. Parametreli sorgu, asgari yetki, açık iş kuralı doğrulaması ve kontrollü dinamik SQL birlikte uygulandığında saldırı yüzeyi belirgin biçimde azalır.

## Veritabanı İçinde Yetki Sınırının Sertleştirilmesi

Parametreli sorgu, SQL enjeksiyonunu önlemenin temelidir; ancak veritabanı içindeki ayrıcalık sınırını tek başına tanımlamaz. Özellikle Oracle ortamında [Oracle Database Vault](/wiki/oracle-database-vault), güçlü veritabanı hesaplarının dahi erişebileceği alanları politika ile sınırlandıran ayrı bir savunma katmanıdır.

## Kaynakça

- **[1]** William G. J. Halfond; Jeremy Viegas; Alessandro Orso. (2006). A Classification of SQL-Injection Attacks and Countermeasures. Proceedings of the IEEE International Symposium on Secure Software Engineering.
- **[2]** Stephen W. Boyd; Angelos D. Keromytis. (2004). SQLrand: Preventing SQL Injection Attacks. Applied Cryptography and Network Security, Springer. [doi:10.1007/978-3-540-24852-1_21](https://doi.org/10.1007/978-3-540-24852-1_21)
- **[3]** Sruthi Bandhakavi; Prithvi Bisht; P. Madhusudan; V. N. Venkatakrishnan. (2007). CANDID: Preventing SQL Injection Attacks Using Dynamic Candidate Evaluations. Proceedings of the 14th ACM Conference on Computer and Communications Security. [doi:10.1145/1315245.1315249](https://doi.org/10.1145/1315245.1315249)

## Bu Çalışmaya Atıf

Köker, M. A. (2021). SQL Enjeksiyonu ve Veri Tabanı Güvenliği. alikoker.com.tr. https://alikoker.com.tr/sql-enjeksiyonu

- BibTeX: https://alikoker.com.tr/sql-enjeksiyonu.bib
- RIS: https://alikoker.com.tr/sql-enjeksiyonu.ris
- CSL-JSON: https://alikoker.com.tr/sql-enjeksiyonu.csl.json
