SELECT * FROM users WHERE name=''; DROPTABLE users; --';user input escaped the stringSQL injection

SQL Enjeksiyonu

11 dk okumaGüvenlik

SQL enjeksiyonu, 1990'ların sonlarından bu yana tüm web güvenliği güvenlik açığı listelerinin en üstünde veya yakınında yer aldı. Düzeltme (parametreli sorgular) bilinmektedir, basittir ve yirmi yıldır önerilmektedir. Ancak yine de her hafta yeni SQLi güvenlik açıkları keşfediliyor. Kategori varlığını sürdürüyor çünkü başarısızlık modu incelikli ve birçok çerçevenin varsayılanları kusurlu.

Makalenin tam metni aşağıda İngilizce olarak verilmektedir.

SQL enjeksiyonu (SQLi), bir saldırganın uygulamanın veritabanına gönderdiği bir sorguya SQL kodu enjekte edebileceği bir güvenlik açığı sınıfıdır. Başarılı olursa, saldırgan erişim yetkisine sahip olmadığı verileri okuyabilir, değiştirebilir veya silebilir, bazen veritabanı sunucusunda kod çalıştırabilir ve bazen de uygulamanın kendisine yönelik saldırılara yönelebilir.

Klasik hata

Ders kitabı örneği. Bir uygulama, oturum açma formundan bir kullanıcı adını kabul eder ve arar:

query = "SELECT * FROM user WHERE kullanıcı adı='" + input + "';"

input, alice ise, sorgu şuna dönüşür:

SELECT * FROM user WHERE kullanıcı adı='alice';

Normal. Ancak input, alice' OR '1'='1 ise sorgu şu şekilde olur:

SELECT * FROM kullanıcılar WHERE kullanıcı adı='alice' OR '1'='1';

OR '1'='1' her zaman doğrudur. Sorgu, tablodaki her kullanıcıyı döndürür. Saldırgan, daha gelişmiş verilerle tabloları boşaltabilir, kayıtları değiştirebilir veya daha da ilerleyebilir.

Saldırı kategorileri

  • Klasik / bant içi SQLi. Enjekte edilen sorgunun sonuçları uygulamanın yanıtında görünür. Saldırgan verileri doğrudan okur.
  • Blind SQLi. Yanıtta hiçbir veri görünmez, ancak uygulamanın davranışı, enjekte edilen sorgunun doğru veya yanlış döndürmesine bağlı olarak değişir. Saldırgan, "yönetici parolasının ilk karakteri 'a' mı?" gibi sorular sorarak verileri teker teker çıkarır.
  • Zamana dayalı kör SQLi. Saldırgan, bir koşul doğrulandığında veritabanının yavaş yanıt vermesini sağlamak için SLEEP() veya eşdeğerini kullanır. Veri sızması daha da yavaştır, ancak uygulama yanıt geri bildirimi vermediğinde çalışır.
  • Bant dışı SQLi. Saldırgan, veritabanını kandırarak kontrol ettiği bir sunucuya veri sızdıran harici bir ağ bağlantısı (DNS araması, HTTP isteği) yapması için veritabanını kandırır.
  • İkinci dereceden SQLi. Kötü amaçlı giriş, önce veritabanını, daha sonra güvenli olmayan bir şekilde okuyup başka bir sorguda kullanmasını sağlar. Ekleme, girişten farklı bir bağlamda gerçekleşir.

Düzeltme: parametreli sorgular

Kullanıcı girişiyle bir veritabanını sorgulamanın doğru yolu, parametre yer tutucularını kullanmaktır, asla dizeleri birleştirmemektir. Temelde her dilde:

// Python (psycopg2)
imleç.execute("SELECT * FROM user WHERE kullanıcı adı=%s", (giriş,))

//Java
stmt = conn.prepareStatement("SELECT * FROM user WHERE kullanıcı adı=?");
stmt.setString(1, giriş);

// JavaScript (sayfa)
client.query("SELECT * FROM user WHERE kullanıcı adı=$1", [input]);

Sürücü, SQL ve parametre değerlerini ayrı ayrı gönderir. Veritabanı hiçbir zaman giriş verilerini SQL sözdizimi ile karıştırmaz. Giriş tırnak işaretleri, noktalı virgüller, OR cümleleri veya başka herhangi bir SQL sözdizimi içerse bile veri olarak kabul edilir.

Bu işe yarar. Yirmi yıldır önerilen yaklaşım budur. Zorluk teknik değil; kod tabanındaki her sorgunun onu kullanmasını sağlıyor.

ORM'ler otomatik olarak güvenli değildir

Object-İlişkisel Eşleyiciler (ActiveRecord, Sequelize, Hibernate, SQLAlchemy) varsayılan olarak parametreli sorgular kullanır; bu harika bir şeydir. Ancak her ORM'de kaçış kapakları vardır:

  • raw() isteğe bağlı SQL dizeleri alan yöntemler
  • String tabanlı ORDER BY cümlecikleri (sütun adları parametrelendirilemez)
  • Sorgulara enterpolasyonlu tablo adları
  • Kendileri tarafından saklanan prosedürler concatenate

Modern SQLi hataları genellikle ana CRUD kod yolunda değil, bu uç durumlarda görünür.

NoSQL enjeksiyonu

Desen SQL'e özgü değildir. MongoDB, Redis, ElasticSearch, GraphQL — kullanıcılardan yapılandırılmış girdi kabul eden herhangi bir sorgu dili, girdi doğrulanmazsa enjekte edilebilir. MongoDB'nin $ne, $gt, $regex operatörleri, JSON yükleri tam olarak şema kontrolünden geçirilmediğinde yaygın enjeksiyon vektörleridir.

Derinlemesine savunma

Parametrelendirmenin ötesinde sorgular:

  • Ldoğu ayrıcalıklı veritabanı hesapları. Uygulama, yalnızca ihtiyaç duyduğu izinlere sahip bir kullanıcıya bağlanmalıdır. Salt okunur yollar salt okunur kimlik bilgilerini kullanır. SQLi'den yararlanıldığında hasarı sınırlar.
  • Giriş doğrulama. Girişleri beklenen formatlarla sınırlandırın. Yararlıdır ancak tek başına yeterli değildir.
  • Web Uygulaması Güvenlik Duvarları (WAF'ler). Belirgin SQLi denemeleriyle desen eşleştirme. Atlanabilir ancak saldırganları yavaşlatır.
  • Statik analiz. Dize ile birleştirilmiş sorgular için kaynağı tarayan araçlar. Modern IDE'ler bunları işaretler.
  • Veritabanı güçlendirme. Gereksiz özellikleri devre dışı bırakın (MSSQL'de xp_cmdshell, PostgreSQL'de tehlikeli uzantılar).

Ünlü SQLi olayları

  • 2007 TJX — 94 milyon kredi kartı. Wi-Fi güvenliğinin ihlaliyle başladı ancak dahili veritabanlarından sızmak için SQLi kullanıldı.
  • 2008 Heartland — 130 milyon kart kaydı. SQLi ağa ilk erişimi sağladı.
  • 2012 LinkedIn — SQLi aracılığıyla 117 milyon parola karması sızdırıldı.
  • 2017 Equifax — Apache Struts güvenlik açığı ancak SQLi, güvenlik ihlali sonrası verilerin bir parçasıydı sızıntı.
  • 2020'ler boyunca — SaaS şirketlerinde, e-ticaret sitelerinde, devlet kurumlarında sayısız küçük ihlal.

Kategori onlarca yıllık ve hâlâ çok canlı.

Sık sorulan sorular

SQL enjeksiyonu hala yaygın mı?
Evet. OWASP'nin İlk 10 listesinde Enjeksiyon (SQLi dahil) her yıl ilk üç kategoride yer almaktadır. Hata ödül programları her hafta SQLi raporlarını görür. Modern çerçeveler ana kod yollarındaki sıklığını azaltmıştır ancak eski uygulamalar, uç durumlar ve ORM kaçış kapakları kategoriyi canlı tutmaktadır.
Web Uygulaması Güvenlik Duvarı tüm SQL enjeksiyonunu durdurabilir mi?
Hayır. WAF'ler bariz kalıpları yakalar ve tecrübesiz saldırganları durdurur, ancak bilgili saldırganlar farklı kodlamalar, yorum ekleme, alternatif SQL sözdizimi gibi geçişler yapabilir. WAF'ler kullanışlı bir katmandır; uygulamada güvenli sorgu oluşturmanın yerini almazlar.
HTTPS SQL enjeksiyonunu engelliyor mu?
Hayır. SQLi, uygulama katmanındaki bir güvenlik açığıdır. HTTPS, aktarım halindeki verileri korur ancak içeriği doğrulamaz. Saldırganın kötü niyetli girişi, herkesinki gibi HTTPS aracılığıyla gelir; Uygulama, onu güvenli bir şekilde işleyen veya işlemeyen şeydir.
NoSQL veritabanları bağışık mıdır?
Hayır. NoSQL enjeksiyonu kendi kategorisidir. MongoDB, Elasticsearch ve diğerleri, kesin olarak doğrulanmadığı takdirde değiştirilebilecek yapılandırılmış sorgu girişini kabul eder. Koruma kalıpları benzerdir (kullanıcı girişini veri olarak ele alın, asla sorgu yapısı olarak ele almayın) ancak belirli saldırılar farklıdır.
Kendi sitemi SQL enjeksiyonu için nasıl test ederim?
Sqlmap gibi araçlar, yaygın SQLi kalıplarının test edilmesini otomatikleştirir; OWASP ZAP ve Burp Suite tarayıcılar içerir. Geliştiriciler için en güvenilir kontrol, dizeyle birleştirilmiş sorgular için kod incelemesi ve statik analizdir. Sızma testi görevleri özellikle SQLi değerlendirmesini içerir.
SQL Enjeksiyonunun Açıklaması: Hiçbir Zaman Tam Olarak Ölmeyen Web Güvenlik Açığı