SQL Injection, saldırganların veritabanına yetkisiz bir şekilde SQL sorguları göndermelerine olanak veren kritik bir güvenlik zafiyetidir.
Bu güvenlik zafiyetinden yararlanabilen saldırganlar, veritabanında bulunan kritik verilere erişim sağlayabilirler ve veritabanı üzerinde; ekleme, silme, değiştirme gibi işlemler yapabilirler.
SQL Injection zafiyeti OWASP 2017 TOP 10 listesinde ilk sırada yer almaktadır.
Aşağıda SQL Injection zafiyetinden yararlanarak veritabanı yönetimi sisteminin versiyon bilgisinin elde edildiği bir örnek yapıldı. Resim 1.1’de uygulamanın gerçekleştirildiği örnek bir laboratuvar ortamı yer almaktadır.
Senaryoya göre 192.168.35.1 IP adresine sahip olan bir saldırgan, 192.168.35.149 IP adresli IIS sunucusunda çalışan web uygulamasındaki “blog.aspx” sayfasının id parametresi üzerinden SQL Injection zafiyetini tetikleyerek 192.168.35.150 IP adresli MSSQL (Microsoft SQL Server) sunucusuna SQL sorguları göndermektedir. Resim 1.2’de web uygulamasında bulunan blog.aspx sayfası yer almaktadır.
Sayfada yer alan id parametresine göre veritabanında yer alan kayıtlar web sayfasında listelenmektedir. Ancak bu parametre SQL Injection zafiyeti içermektedir. Resim 1.3’te id parametresine “ ‘ (tırnak)“ işareti atılarak zafiyet tetiklendi.
id parametresine ‘ (tırnak) işareti eklenerek istek yapılması sonucunda SQL sunucusundan hata mesajı alındı. Bunun sebebi, web uygulamasının id parametresine atanan değeri SQL sorgusunun devamı gibi algılamasıdır. Bu nedenle id parametresine ‘ (tırnak) işaretinin atanması sorguyu bozduğundan dolayı hata mesajı döndü ve bu hatadan SQL Injection zafiyetinin olduğu anlaşıldı. Saldırganlar, id parametresine var olan sorgunun devamı olacak nitelikte ek sorgular ekleyerek kendi SQL sorgularını çalıştırabilirler. Resim 1.4’te id parametresine UNION deyimiyle birlikte bir SELECT sorgusu (1 UNION SELECT 1,’SQL INJECTION’,@@version–) atanarak SQL sunucusunun versiyon bilgisi elde edildi.
Resim 1.5’te SQLMAP aracı kullanılarak SQL sunucusundaki veritabanı adları elde edildi.
Saldırganlar bu zafiyetten yararlanarak SQL sunucusunu tahrip etmeye yönelik sorgular çalıştırabilirler. Bu yazıda “SQL Server Stored Procedure” kullanılarak, SQL Injection zafiyetinin engellenmesinden bahsedilecektir.
Stored Procedure Kullanılarak SQL Injection Zafiyetinin Engellenmesi
Stored Procedure, belirli SQL sorgularının çalıştırılması için yapılandırılan SQL kod parçacıklarıdır. Bir stored procedure ilk oluşturulduğunda SQL sorgularını derler ve daha sonraki stored procedure çağrılarında bu sorguları tekrar tekrar derlemez. Bu nedenle SQL sorgularının stored procedure nesnelerinde yer alması zamandan kazanç ve performans artışı sağlar.
Bir stored procedure, doğru şekilde oluşturulduğunda SQL Injection saldırılarının önüne geçilebilir. Çünkü, stored procedure ile kullanıcı girdileri SQL sorgusunun devamı olarak değil, bir değer olarak kabul edilir. SQL sunucusuna gönderilen kullanıcı girdilerinin stored procedure tarafından bir değer olarak algılanabilmesinden dolayı, SQL Injection zafiyetini tetikleyebilecek olan tüm girdiler SQL sorgusunu etkilemeyecektir.
Resim 2.1’de id parametresinden gelen değere göre tablodaki verileri listeleyen bir stored procedure tanımlandı.
Bu prosedür içerisinde @id adlı sayısal bir değişken, @sqlcmd ve @params adlı metinsel değişkenler tanımlandı. @id değişkeni web uygulamasından gelen id parametresine atanan değeri, @sqlcmd değişkeni SQL sorgusunu ve @params değişkeni @id değişkeninin tanımını içermektedir. Ardından bu değişkenler varsayılan olarak tanımlı olan sp_executesql adlı stored procedure ile birlikte kullanıldı. Böylece sp_executesql prosedürünün aldığı parametreler birer değer olarak kabul edildiğinden dolayı, id parametresine atanan değerin sayısal bir değer olmaması durumunda SQL sorgusu çalışmayacaktır.
Prosedür içerisinde SELECT sorgusunun direk çalıştırılması sağlanabilirdi. Resim 2.2’de SELECT sorgusunun direk çalıştırıldığı bir stored procedure tanımlandı.
Fakat saldırganlar web uygulaması üzerinde id parametresine sayısal bir değer atadıktan sonra, devamında kendi sorgularını ekleyebilirler ve SQL Injection zafiyetini tetikleyebilirler. Bunun sebebi, stored procedure içerisinde yer alan sorgunun id parametresine atanan veriyi bir değer olarak algılamasına rağmen, devamında yazılanları sorguya dahil etmesinden dolayı kaynaklanmaktadır. Örneğin; id parametresine 1;DROP TABLE dbo.music—ifadesinin atanması durumunda “ ; (noktalı virgül)” işaretinden önce gelen 1 değeri sayısal bir ifade olduğu için, prosedür bu değeri kabul edecektir. Ardından SQL Server, noktalı virgül işaretini bu sorguyu bitiren bir karakter olarak algılayacaktır ve devamında gelen DROP TABLE dbo.music ifadesini bir SQL sorgusu olarak çalıştıracaktır. sp_executesql prosedürü ise bu durumun önüne geçer ve id parametresine atanan değer sadece sayısal bir değer olmadığı sürece hiçbir girdiyi kabul etmez. Örneğin; id parametresine yeniden 1;DROP TABLE dbo.music— ifadesinin atanması durumunda, sp_executesql bu ifadenin tamamını ele alacaktır ve ifade sadece sayısal karakterlerden oluşmadığı için SQL sorgusu çalışmayacaktır. Resim 2.3’te, Resim 2.1’de yer alan prosedürü çağıran ve id parametresini bu prosedüre bir değer olarak atayan C# kodları yer almaktadır.
Bu kodların yer aldığı web uygulaması yeniden çalıştırıldı ve id parametresine SQL Injection zafiyetini tetikleyebilecek bir sorgu atandı. Resim 2.4’te id parametresine SQL Injection zafiyetini tetikleyebilecek bir sorgu atanmıştır.
Sorgunun atanması ve istek yapılması sonucunda SQL sunucusundan hata alındı. Ancak bu hata SQL Injection zafiyetinden kaynaklanan bir hata değildir. id parametresi sayısal bir değer almadığı için sunucu tarafından hata alındı ve sadece sayısal bir değer girilmediği sürece hiçbir girdi SQL sorgusunu etkilemeyecektir.
Resim 2.5 ‘te yeniden çalıştırılan SQLMAP aracının sonuçları yer almaktadır.
Yazar: Ramin Karimkhani