SQL Injection

SQL Injection, veri tabanına dayalı uygulamalara saldırmak için kullanılan bir atak tekniğidir; burada saldırgan SQL dili özelliklerinden faydalanarak standart uygulama ekranındaki ilgili alana yeni SQL ifadelerini ekler. (Örneğin saldırgan, veritabanı içeriğini kendisine aktarabilir). SQL Injection, uygulamaların yazılımları içindeki bir güvenlik açığından faydalanır, örneğin, uygulamanın kullanıcı giriş bilgileri beklediği kısma SQL ifadeleri gömülür, eğer gelen verinin içeriği uygulama içerisinde filtrelenmiyorsa veya hatalı şekilde filtreleniyorsa, uygulamanın, içine gömülmüş olan kodla beraber hiçbir hata vermeden çalıştığı görülür. SQL Injection, çoğunlukla web siteleri için kullanılan bir saldırı türü olarak bilinse de SQL veritabanına dayalı tüm uygulamalarda gerçeklenebilir.
SQL injection saldırıları, saldırganların, sistemdeki kullanıcılardan birinin bilgileriyle giriş yapmasına,  mevcut verilere müdahale etmesine, bazı işlemleri iptal etmesine veya değiştirmesine, veri tabanındaki tüm verileri ifşa etmesine, veri tabanındaki tüm verileri yok etmesine, veri tabanı sunucusunda sistem yöneticisi olmasına olanak sağlar.
2012'de yapılan bir araştırmada,bir web uygulamasının ayda ortalama 4 saldırı aldığı ve perakendecilerin diğer endüstrilerden iki kat fazla saldırı aldığı görülmüştür.

Tarih

SQL Injection, 1998 yılı civarında tartışılmaya başlanmıştır. Örneğin, 1998'de Phrak dergisinde yayımlanan bir makalede SQL Injection'dan söz edilmiştir. 

Blind SQL injection

Blind SQL injection, bir web uygulaması bir SQLI'na karşı açık olduğunda kullanılır, ancak sonuçları saldırgan tarafından görülemez.Güvenlik açığı bulunan sayfada veriler ifşa edilemez ama SQL ifadesinin içine gömülmüş olan mantıksal ifade nedeniyle değiştirilmiş veriler görüntülenebilir.

İkincil SQL injection (Second order SQL injection)

İkincil SQL injection, kötü amaçlı kodlar içeren değerlerin gönderilir gönderilmez yürütülmeyip, bir süre tutulduğu zaman oluşur. Uygulama SQL ifadesini doğru şekilde encode edip, geçerli SQL ifadesi olarak depo edebilir. Sonrasında SQL injectiona karşı denetimsiz olan uygulamanın başka bir kısmında, depolanan SQL ifadesi çalıştırılır. Bu saldırıyı gerçeklemek için saldırganın, gönderilen değerlerin daha sonra nasıl kullanıldığına dair daha fazla bilgiye sahip olması gerekir. Otomatik web uygulaması güvenlik tarayıcıları, bu tür bir SQL injection'ları kolaylıkla algılayamaz. Dolayısyla kötü niyetli yazılımların kodun handi kısmında olduğu manuel olarak kontrol edilmelidir.

Saldırılara karşı önlemler

SQL injection, iyi bilinen bir saldırıdır ve basit önlemlerle kolayca önlenebilir. 2015'te Talktalk'daki bariz bir SQL injection saldırısı sonrasında BBC, böyle büyük bir şirketin sql injection açıklarının bulunmasının güvenlik uzmanlarını şaşırttığını belirtti.

Parametreleştirilmiş ifadeler

Çoğu uygulama geliştirme platformunda, parametre olarak kullanıcıdan gelen veri yerine parametrik ifadeler kullanılır.(placeholder veya bind variable olarak da isimlendirilirler.) Bir placeholder sadece verilen tipte veri saklar. Dolayısıyla SQL injection yalnızca ilginç (ve muhtemelen geçersiz) bir parametre değeri olarak ele alınır.
Çoğu durumda, SQL ifadesi belirlidir ve her parametre tablo olarak değil, bir skaler olarak saklanır. Kullanıcıdan gelen veri bu parametreye atanır.

Kod seviyesinde zorlamak (Enforcement at the coding level)

object-relational mapping kütüphanelerini kullanmak, SQL kod yazma gereksinimini ortadan kaldırır. Etkin olan ORM kitaplığı, object-oriented koddan parametrik SQL ifadeleri üretir.

Escaping

SQL'de özel anlamları olan karakterlerden kaçınmak gereklilir. SQL DBMS, hangi karakterlerin  özel bir anlam taşıdığını açıklar ve kapsamlı bir blacklist sunar. Örneğin her parametre içindeki tek tırnak işareti('), geçerli bir SQL string literal oluşturmsk için iki tek tırnak ile değiştirilir.('') mysqli_real_escape_string();fonksiyonunu kullanarak parametrelerdern kaçınmak yaygın bir yöntemdir.
$mysqli = new mysqli('hostname', 'db_username', 'db_password', 'db_name');$query = sprintf("SELECT * FROM `Users` WHERE UserName='%s' AND Password='%s'",
                  $mysqli->real_escape_string($username),
                  $mysqli->real_escape_string($password));$mysqli->query($query);
Bu fonksiyon şu karakterlerin başına backslash (\) ekler. \x00, \n, \r, \, ', " \x1a. MySQL'e bir sorgu göndermeden önce veri güvenliğini sağlamak için kullanılır.
PHP'de birçok vertabanı türü için birçok fonksiyon var örneğin pg_escape_string() fonsiyonu PostgreSQL için. Slash eklemek için kullanılan addslashes (string $ str) fonksiyonu escaping karakterler için kullnılır. Veri tabanında sorgulanacak karakterlerin başına  backslash (\) eklenmiş bir string döndürür. Bu karakterler tek tırnak işareti ('), çift tırnak işareti ("), backslash (\) ve NUL (NULL bayt) şeklindedir.
İnput güvenliğini sağlamak için şeffaf bir katman oluşturmak hata eğilimini azaltabilir, ancak tamamen ortadan kaldırmaz.

Örüntü kontrolü

Integer, float, boolean, string parametreleri, değerlerinin belirtilen tür için geçerli olup olmadığı kontrol edilebilir. Stringlerin başka paternlara göre de kontrol edilmesi gerekebilir. (tarih, UUID, sadece alfanumerik, vb.)

Veri tabanı izinleri

Web uygulamaları tarafından verilen, veri tabanında oturum açma izinlerini kısıtlamak, web uygulamalarındaki açıkları kullanan bir SQL injection saldırılarının etkinliğini azaltmaya yardımcı olabilir.
Örneğin, Microsoft SQL Server'da bir veritabanı oturum açma işleminde bazı sistem tablolarına erişim kısıtlanabilir bu sayede veritabanındaki tüm text sütunlarına JavaScript eklemeyi deneyen kötü niyetli yazılımlar sınırlandırılmış olur.
deny select on sys.sysobjects to webdatabaselogon;deny select on sys.objects to webdatabaselogon;deny select on sys.tables to webdatabaselogon;deny select on sys.views to webdatabaselogon;deny select on sys.packages to webdatabaselogon;