SQL-Injection, SQL kullanan Web uygulamalarında karşilaşilan en popüler güvenlik problemi olduğundan; çok uzun girdiler (overlong input) gibi SQL sorgularıyla ilgili diğer güvenlik tehditleri üzerinde yeterince durulmamaktadır. Atlanan bu güvenlik tehditleri de, SQL-Injection’lar gibi ciddi problemler oluşturma potansiyeline sahiptir.
Bu görmezden gelme hali, çok uzun girdilerin genellikle buffer overflow tarzı problemlere sebep olmasından ileri geliyor olabilir. Zira, buffer overflow’lar güvenlik uzmanlarının dahi hakkında pek az bilgiye sahip olduğu ve bu sebeple üzerinde dikkat göstermediği bir mevzu olarak karşimıza çikmaktadir. Buna karşin, hiçkimsenin bahsetmediği, SQL sorgularıyla alakalı çok uzun girdilerden kaynağını alan pek çok farklı ve ciddi problemin varlığı da bir hakikattir.
max_packet_size
MySQL’de; SQL istemcisi ile sunucusu arasında, gönderilen maksimum veri paketi boyutunu kontrol eden ve varsayılan değeri 1 megabyte olarak belirlenmiş olan max_packet_size adlı bir konfigürasyon seçeneği mevcuttur. Sorgular veya sonuç satırları tek bir paket içerisine uymayacak kadar büyük olursa bir hata oluşur ve çok uzun SQL sorguları sunucuya ulaştırılmaz, dolayısıyla da çalistirilmaz.
Bu durum, SQL sorgularında kullanılan türden uzun veriler sağlayabilen saldırganlarca ciddi güvenlik tehlikelerine sebep olacak şekilde suiistimal edilebilir. Bu meseleye güzel bir örnek, log sorgularında karşimıza çikmaktadir. Bu sorgular HTTP User-Agent, Session ID ve log mesajı gibi farklı türden pek çok veriyi geniş bir paket halinde gönderme imkanı tanıdığından, maksimum paket boyutunun aşilmasına da sebep olabilir.
Gerçek hayattan bir örnek daha vermek gerekirse; evvela belirtilen parametrelere uyan oturumları bir PHPi dizisine aktaran, daha sonra çoklu seviye temizliğini gerçekleştiren ve son olarak da seçilen tüm oturum id’lerini tek bir silme sorgusunun içerisine aktaran bir oturum tablosu temizleme işleminden söz edebiliriz. Anlaşilabileceği gibi, tablodan silinmesi gereken oturumların çok sayıda tanımlayıcı bilgiye sahip olduğu durumlarda sorgu çok uzun bir hal alır. Sonuç olarak, uygulama kısa bir zamanda çok sayıda oturumla şişirildiğinde, kullanılmayan gereksiz oturumlar daha sonra silinemez hale gelir.
Dolayısıyla Web uygulaması geliştiriciler, sunucuya çok uzun veriler göndermediklerinden emin olmalıdır. Önceden hazırlanmış ifadeler (prepared statement) kullanıp kullanmamak burada önemli değildir.
SQL Sütun Kesintisi Açıkları
Kullanıcı girdileri uygulama içerisinde uzunluk yönünden kontrol edilmediğinde, SQL sütun kesintisi açıkları ortaya çikabilir. SQL sütun kesintisi açığı, veritabanına veri eklenmesi esnasında uzunluktan dolayı kesilen çok uzun girdiler sebebiyle oluşan açıkları ifade etmek üzere kullandığım isimdir. Varsayılan modda MySQL, tanımlı olan maksimum sütun genişliği değerinden daha büyük olan girdileri keser, maksimum boyuta kadar gönderilen kısmı işler ve yalnızca bu işleme dair bir uyarı verir. Bu uyarılar genellikle web uygulamaları tarafından görülmez ve dikkate alınmaz. MySQL’de sql_mode, STRICT_ALL_TABLES şeklinde belirlenebilir ve bu uyarıların hata şekline dönüştürülmesi sağlanabilir; fakat uygulamalar genelde varsayılan modu kullanan sunucularda çalisir ve uygulamanın kendisi strict modu kullanıyor olsa bile ilk etapta bu hata üretilemez. Sonuç olarak uygulamalarda uzunluk kontrolüne başvurulması hayatî ehemmiyettedir.
Veri eklemelerindeki kesintilerin ne gibi problemlere sebep olabileceğini anlamak için aşağıdaki örnek üzerinde düşünebilirsiniz.
* Uygulama, yeni kullanıcıların kaydolabileceği bir forumdur.
* Administrator yetkisine sahip kullanıcının ismi bilinmektedir (örnegin admin).
* MySQL, varsayılan modda kullanılmaktadır.
* Kullanıcı isimlerinin uzunluğuna dair, uygulamada herhangi bir sınırlama kontrolü mevcut değildir.
* Veritabanında, kullanıcı isimlerini tutma işine tahsis edilmiş sütun 16 karaktere kadar veri kabul edecek şekilde düzenlenmiştir.
Potansiyel bir saldırgan bu şartlar altında "admin " nickini kaydetmeyi deneyebilir, fakat ‘isAlreadyRegistered’ kontrolü SQL sorgusunda devreye gireceğinden saldırgan bu hususta muvaffak olamaz.
SELECT * FROM user WHERE username=’admin ’
MySQL, varsayılan modda metin karşilaştırmalarını Binary modunda değil de güvenlik açısından daha rahat modlarda yapmaktadır. Mesela bu modlarda metin sonlarındaki boşluk karakterleri yok sayıldığından, "admin " ve "admin" ifadeleri aynı kabul edilmektedir. Dolayısıyla uygulama yeni kullanıcı kaydına izin vermeyecektir.
Fakat saldırgan "admin x" nickini kaydetmeyi denediğinde; uygulama, veritabanında bu kullanıcı ismini arayacak, fakat 16 karakterle sınırlanmış bir veritabanı alanında 17 karakterli bir veriyi bulmak mümkün olmayacağından girilen verinin karşilığı veritabanında çikmayacaktir. Bu durumda uygulama yeni kullanıcı ismini kabul ederek veri tabanına ekleyecektir. Yalnız veritabanı yalnızca 16 karakter aldığından, yerleştirilen bu veri 16 karaktere kadar kesilecek ve boşluk karakterleri de dikkate alınmadığından netice itibarıyla admin nicki veritabanında iki defa yer bulacaktır.
Sonuç olarak kullanıcı tablosu, sondaki boşlukların yok sayılmasından dolayı aynı nicke sahip olan iki kullanıcıyı barındırmaktadır ve yukarıdaki select sorgusu çalistirildiginda her iki nick de döner. Bu noktada potansiyel bir tehlike oluşur, zira artık iş uygulamanın nick’leri ne şekilde işlediğine kalmıştır. Mesela aşağıda göstereceğimiz kod örnegi, öncesinde:
SELECT username FROM users WHERE username = ? AND passhash = ?
sorgusuyla kullanıcı şifresinin doğruluğunu test ettikten sonra kullanıcı adına bakarak kullanıcıyla ilgili verileri kontrol eden bir uygulamada açık doğurabilecek tarzdandır:
$userdata = null;
if (isPasswordCorrect($username, $password)) {
$userdata = getUserDataByLogin($username);
...
}
SELECT * FROM users WHERE username = ?
İkinci admin kullanıcısını oluşturan kişi saldırganın bizzat kendisi olduğundan, bu kontrolü geçmesini sağlayacak şifreyi de bilmektedir. Gerçek admin kullanıcısı tablonun başinda yer alacağından, daha sonra kullanıcı verisi isme göre kontrol edilirken ilk etapta döndürülecek olan kullanıcı da admin yetkilerine sahip olan kullanıcıdır.
Sonuç:
Burada bahsedilen iki problem de, web uygulamaları tarafından dikkate alınması gereken yeni tehlikelerdir; zira her ikisi de ciddi güvenlik problemlerine sebep olabilir. Bu açıklar bundan böyle bilinir hale geldiğinden, takip eden birkaç hafta içerisinde özellikle açık kodlu yazılımlarda bu noktalarla ilgili tavsiyeler görmek şaşirtıcı olmayacaktır.
Bu görmezden gelme hali, çok uzun girdilerin genellikle buffer overflow tarzı problemlere sebep olmasından ileri geliyor olabilir. Zira, buffer overflow’lar güvenlik uzmanlarının dahi hakkında pek az bilgiye sahip olduğu ve bu sebeple üzerinde dikkat göstermediği bir mevzu olarak karşimıza çikmaktadir. Buna karşin, hiçkimsenin bahsetmediği, SQL sorgularıyla alakalı çok uzun girdilerden kaynağını alan pek çok farklı ve ciddi problemin varlığı da bir hakikattir.
max_packet_size
MySQL’de; SQL istemcisi ile sunucusu arasında, gönderilen maksimum veri paketi boyutunu kontrol eden ve varsayılan değeri 1 megabyte olarak belirlenmiş olan max_packet_size adlı bir konfigürasyon seçeneği mevcuttur. Sorgular veya sonuç satırları tek bir paket içerisine uymayacak kadar büyük olursa bir hata oluşur ve çok uzun SQL sorguları sunucuya ulaştırılmaz, dolayısıyla da çalistirilmaz.
Bu durum, SQL sorgularında kullanılan türden uzun veriler sağlayabilen saldırganlarca ciddi güvenlik tehlikelerine sebep olacak şekilde suiistimal edilebilir. Bu meseleye güzel bir örnek, log sorgularında karşimıza çikmaktadir. Bu sorgular HTTP User-Agent, Session ID ve log mesajı gibi farklı türden pek çok veriyi geniş bir paket halinde gönderme imkanı tanıdığından, maksimum paket boyutunun aşilmasına da sebep olabilir.
Gerçek hayattan bir örnek daha vermek gerekirse; evvela belirtilen parametrelere uyan oturumları bir PHPi dizisine aktaran, daha sonra çoklu seviye temizliğini gerçekleştiren ve son olarak da seçilen tüm oturum id’lerini tek bir silme sorgusunun içerisine aktaran bir oturum tablosu temizleme işleminden söz edebiliriz. Anlaşilabileceği gibi, tablodan silinmesi gereken oturumların çok sayıda tanımlayıcı bilgiye sahip olduğu durumlarda sorgu çok uzun bir hal alır. Sonuç olarak, uygulama kısa bir zamanda çok sayıda oturumla şişirildiğinde, kullanılmayan gereksiz oturumlar daha sonra silinemez hale gelir.
Dolayısıyla Web uygulaması geliştiriciler, sunucuya çok uzun veriler göndermediklerinden emin olmalıdır. Önceden hazırlanmış ifadeler (prepared statement) kullanıp kullanmamak burada önemli değildir.
SQL Sütun Kesintisi Açıkları
Kullanıcı girdileri uygulama içerisinde uzunluk yönünden kontrol edilmediğinde, SQL sütun kesintisi açıkları ortaya çikabilir. SQL sütun kesintisi açığı, veritabanına veri eklenmesi esnasında uzunluktan dolayı kesilen çok uzun girdiler sebebiyle oluşan açıkları ifade etmek üzere kullandığım isimdir. Varsayılan modda MySQL, tanımlı olan maksimum sütun genişliği değerinden daha büyük olan girdileri keser, maksimum boyuta kadar gönderilen kısmı işler ve yalnızca bu işleme dair bir uyarı verir. Bu uyarılar genellikle web uygulamaları tarafından görülmez ve dikkate alınmaz. MySQL’de sql_mode, STRICT_ALL_TABLES şeklinde belirlenebilir ve bu uyarıların hata şekline dönüştürülmesi sağlanabilir; fakat uygulamalar genelde varsayılan modu kullanan sunucularda çalisir ve uygulamanın kendisi strict modu kullanıyor olsa bile ilk etapta bu hata üretilemez. Sonuç olarak uygulamalarda uzunluk kontrolüne başvurulması hayatî ehemmiyettedir.
Veri eklemelerindeki kesintilerin ne gibi problemlere sebep olabileceğini anlamak için aşağıdaki örnek üzerinde düşünebilirsiniz.
* Uygulama, yeni kullanıcıların kaydolabileceği bir forumdur.
* Administrator yetkisine sahip kullanıcının ismi bilinmektedir (örnegin admin).
* MySQL, varsayılan modda kullanılmaktadır.
* Kullanıcı isimlerinin uzunluğuna dair, uygulamada herhangi bir sınırlama kontrolü mevcut değildir.
* Veritabanında, kullanıcı isimlerini tutma işine tahsis edilmiş sütun 16 karaktere kadar veri kabul edecek şekilde düzenlenmiştir.
Potansiyel bir saldırgan bu şartlar altında "admin " nickini kaydetmeyi deneyebilir, fakat ‘isAlreadyRegistered’ kontrolü SQL sorgusunda devreye gireceğinden saldırgan bu hususta muvaffak olamaz.
SELECT * FROM user WHERE username=’admin ’
MySQL, varsayılan modda metin karşilaştırmalarını Binary modunda değil de güvenlik açısından daha rahat modlarda yapmaktadır. Mesela bu modlarda metin sonlarındaki boşluk karakterleri yok sayıldığından, "admin " ve "admin" ifadeleri aynı kabul edilmektedir. Dolayısıyla uygulama yeni kullanıcı kaydına izin vermeyecektir.
Fakat saldırgan "admin x" nickini kaydetmeyi denediğinde; uygulama, veritabanında bu kullanıcı ismini arayacak, fakat 16 karakterle sınırlanmış bir veritabanı alanında 17 karakterli bir veriyi bulmak mümkün olmayacağından girilen verinin karşilığı veritabanında çikmayacaktir. Bu durumda uygulama yeni kullanıcı ismini kabul ederek veri tabanına ekleyecektir. Yalnız veritabanı yalnızca 16 karakter aldığından, yerleştirilen bu veri 16 karaktere kadar kesilecek ve boşluk karakterleri de dikkate alınmadığından netice itibarıyla admin nicki veritabanında iki defa yer bulacaktır.
Sonuç olarak kullanıcı tablosu, sondaki boşlukların yok sayılmasından dolayı aynı nicke sahip olan iki kullanıcıyı barındırmaktadır ve yukarıdaki select sorgusu çalistirildiginda her iki nick de döner. Bu noktada potansiyel bir tehlike oluşur, zira artık iş uygulamanın nick’leri ne şekilde işlediğine kalmıştır. Mesela aşağıda göstereceğimiz kod örnegi, öncesinde:
SELECT username FROM users WHERE username = ? AND passhash = ?
sorgusuyla kullanıcı şifresinin doğruluğunu test ettikten sonra kullanıcı adına bakarak kullanıcıyla ilgili verileri kontrol eden bir uygulamada açık doğurabilecek tarzdandır:
$userdata = null;
if (isPasswordCorrect($username, $password)) {
$userdata = getUserDataByLogin($username);
...
}
SELECT * FROM users WHERE username = ?
İkinci admin kullanıcısını oluşturan kişi saldırganın bizzat kendisi olduğundan, bu kontrolü geçmesini sağlayacak şifreyi de bilmektedir. Gerçek admin kullanıcısı tablonun başinda yer alacağından, daha sonra kullanıcı verisi isme göre kontrol edilirken ilk etapta döndürülecek olan kullanıcı da admin yetkilerine sahip olan kullanıcıdır.
Sonuç:
Burada bahsedilen iki problem de, web uygulamaları tarafından dikkate alınması gereken yeni tehlikelerdir; zira her ikisi de ciddi güvenlik problemlerine sebep olabilir. Bu açıklar bundan böyle bilinir hale geldiğinden, takip eden birkaç hafta içerisinde özellikle açık kodlu yazılımlarda bu noktalarla ilgili tavsiyeler görmek şaşirtıcı olmayacaktır.