SQL Injection Atağı Nasıl Yapılır / Önlenir ?


 


SQL Injection Atağı Nasıl Yapılır / Önlenir ?
   
    Bir önceki yazımda Lamer'ların sitemleri nasıl rahatsız ettiklerini ve bir kısım ataklarla ilgili başlıkları kısaca yazmıştım. Bu başlıkda ise sistemlerin artık büyük çoğunluğunun dikkat ettiği / sorunları giderdiği ancak hala büyük bir risk olan SQL Injection ataklarından bahsedeceğim.


    SQL Injection veya Sql enjeksiyon 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 enjeksiyon, 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.Ç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.
    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.

    Başarılı bir Sql enjeksiyon istismarı, hassas verileri veritabanından okuyabilir, veritabanı verilerini değiştirebilir (Ekle / Güncelle / Sil), veritabanındaki yönetim işlemlerini yürütebilir. Sistemi ve bazı durumlarda işletim sistemine komutlar verir.

Tehdit türleri:

  • SQL enjeksiyon saldırıları, saldırganların kimliğini kandırmasına, mevcut verilere müdahale etmesine, işlemlerin iptal edilmesine veya bakiyelerin değiştirilmesine neden olmasına, sistemdeki tüm verilerin tamamen ifşa edilmesine izin verilmesine, verilerin yok edilmesine veya aksi halde kullanılamaması gibi durumlara sebebiyet verir.
  • Daha eski işlevsel arayüzlerde yaygın olması nedeniyle PHP ve ASP uygulamaları ile çok yaygındır. Kullanılabilir programlı arayüzlerin doğasından ötürü, J2EE ve ASP.NET uygulamalarının kolaylıkla SQL enjeksiyonlarından zarar görme olasılığı düşüktür.
  • Saldırılarının şiddeti, saldırganın beceri ve hayal gücüyle sınırlıdır. Genel olarak, SQL enjeksiyonunu yüksek darbe şiddeti olarak düşünün.
    Atak Örneği:
 
    Mesela bir foruma veya e-posta kutunuza giriş yapacaksınız. Kullanıcı adı ve şifrenizi girdiniz. Verileri girdikten sonra;
    SELECT * FROM UYELER
    WHERE kullanıcı_adi = ‘Baris’
    AND sifre = ‘pamuk’ ” 

    şekline benzer bir sql sorgusu oluşturulur. Eğer veritabanında böyle bir kayıt varsa sql sorgusu o kaydı döndürür ve girişiniz sağlanır. Eğer kayıt yoksa tekrar giriş ana sayfasına yönlendirilirsiniz. Aşağıdaki örnek bir koda bakalım:
Kullanici_adi = Request.Form(“username”)
Sifre = Request.Form(“password”)
Set RsLogin = SQLConn.Execute(“select * from Uyeler where username =
 ‘ “ & Kullanici_adi & ” ’ and password = ‘ “ & Sifre & ” ’ ”)
İf RsLogin.EOF and RsLogin.BOF then Response.Redirect “/error.asp”
else Oturum(“login”) = RsLogin(“kullanici_no”)
Response.Redirect ”../”
end if
    Yukarıdaki örnek kod klasik bir oturum açma şeklidir. Bu örneğe basit bir sql aşılama deneyelim ve neler olabilir görelim.

    Öncelikle Kullanici_adi yerine “ ‘ or 1 = 1 ” , Sifre yerine ise “ ‘ or 1 = 1 ” girelim. Bu geliştirme bizim sisteme giriş yapabilmemizi sağlayacaktır. Neden ve nasıl diye sormak çok doğal. Şimdi koda bakalım ve nasıl olduğunu hep beraber inceleyelim. Girdiğimiz değerleri kodda yerlerine koyarsak karşımıza şu şekilde bir kod çıkar.·


Select * from Uyeler where username = ‘ ‘ or 4 = 4 ’ and password = ‘ ‘or 4 = 4 ’

    Sizlerin de farkettiği gibi bu Sql cümlesi şu şekilde yorumlanacaktır. Uyeler tablosundan kullanici_adi alanı boş olanlar ve Sifre alanı boş olanları getir veya 4 eşittir 4 getir. Bu sql cümlesi her zaman doğru dönecek ve Uyeler tablosundan tüm üyeleri listeleyecektir. Çünkü ilk kontrole bakmaksızın son kontrol(4 eşittir 4 kontrolü) her zaman doğru sonuç verecek ve Sql sorgusu çalışıp, Uyeler tablosundan tüm üyeler listelenecektir. Böylece dönen kayıtlardaki ilk kullanici olarak giriş yapmış bulunmaktasınız. Görüldüğü gibi Sql aşılama; Sql cümlelerinin arasına dışarıdan müdahale yapılmasına imkan sağlayıp Sql’i istediğiniz şekilde değiştirmenize izin verir.

    Diğer bir örnek ise Blind (Kör) Sql Injection örneği olsun. Kör SQL enjeksiyonu, veritabanına doğru veya yanlış sorular sorar ve cevapları uygulama yanıtına dayalı olarak belirleyen bir Sql enjeksiyon saldırısı türüdür. Bu saldırı, web uygulaması genel hata mesajlarını gösterecek şekilde yapılandırıldığında, ancak SQL enjeksiyonuna karşı savunmasız kodu azaltmadığında sıklıkla kullanılır. Bir saldırgan SQL enjeksiyonu kullandığında, bazen web uygulaması, SQL sorgusunun sözdiziminin hatalı olduğundan şikayet eden hata iletilerini veritabanından görüntüler. Normal Sql enjeksiyonu ile hemen hemen aynıdır, tek fark, verilerin veritabanından alınma şekli olmasıdır.
  •     Örnek URL:
    http://newspaper.com/items.php?id=
    • Veritabanına aşağıdaki sorguyu göndermeyi deneyeceğiz.

      SELECT title, description, body FROM items WHERE ID = 2
    • Saldırgan daha sonra false döndürmeyi deneyecek bir sorgu çalıştırmayı deneyebilir.

      http://newspaper.com/items.php?id=2 and 1=2
    • Şimdi SQL sorgusu bu şekilde gözükmektedir:
      SELECT title, description, body FROM items WHERE ID = 2 and 1=2
    • Web uygulaması, SQL Enjeksiyonuna karşı savunmasızsa, muhtemelen hiçbir şey döndürmeyebilir. Emin olmak için, saldırgan 'true' değerini döndürecek bir sorgu enjekte edecek:
      http://newspaper.com/items.php?id=2 and 1=1
    • 'True' döndüren sayfanın içeriği 'False' döndüren sayfanın içeriğinden farklıysa, saldırgan yürütülen sorgunun ne zaman doğru veya yanlış döndürdüğünü ayırt edebilir. Bu doğrulandıktan sonra, tek sınırlamalar, veritabanı yöneticisi tarafından ayarlanan ayrıcalıklar, farklı SQL sözdizimi ve saldırganın hayal gücüdür.


        Peki Nasıl Korunuruz?

    •     Veri erişim sorgularında kullanılan girdiyi sınırlandırarak uygulamanızı SQL enjeksiyonundan koruyabilirsiniz. (Regexve çeşitli Regular Expression'lar kullanılabilir.)

          NOT: Girdi sınırlandırırken, kabul edilebilir karakterlerin bir listesini oluşturmak ve listedeki karakterleri reddetmek için düzenli ifadeler kullanmak iyi bir uygulamadır. Ayrıca, kabul edilemez bir karakter, geçerliliği onaylamak için alternatif bir biçimde temsil edilebilir.

      ÖR:

      if (Regex.IsMatch(Request.Cookies["SSN"], "^\d{3}-\d{2}-\d{4}$"))
      {
          // Veritabanı erişimi
      }
      else
      {
          // Yanlış bir istek mesajı
      }
      
      
    •     Veri erişim kodunuzda giriş sınırlaması yapmak.

          Bazı durumlarda, belki de ASP.NET sayfa düzeyi doğrulamasına ek olarak, veri erişim kodunuzda doğrulama sağlamanız gerekir. Veri erişim kodunuzda doğrulama yapmanız gereken iki yaygın durum şunlardır:

      1) Güvenilmeyen müşteriler: Veriler güvenilmeyen bir kaynaktan gelebilir veya verilerin ne kadar geçerli ve kısıtlanmış olduğunu garanti edemezseniz, girdiyi veri erişim rutinlerine sınırlayan onaylama mantığı ekleyin.

      2) Kütüphane kodu: Veri erişim kodunuz çoklu uygulamalar tarafından kullanılmak üzere tasarlanmış bir kitaplık olarak paketlenmişse, veri erişim kodunuz kendi doğrulamasını yapmalıdır çünkü istemci uygulamaları hakkında güvenli bir varsayım yapamazsınız.

          Aşağıdaki örnek, bir veri erişim yordamının, bir SQL deyimindeki parametreleri kullanmadan önce normal ifadeler kullanarak giriş parametrelerini doğrulayabileceğini göstermektedir.

      ÖR:

      public void CreateNewUserAccount(string name, string password)
      {
          // Kontrol adında yalnızca küçük veya büyük harf 
          // nokta veya boşluk bulunur.Ayrıca 1 ile 40 karakter uzunluğunda olduğunu
          // kontrol eder.
      
          if ( !Regex.IsMatch(userIDTxt.Text, @"^[a-zA-Z'./s]{1,40}$"))
            throw new FormatException("Invalid name format");
      
          // Parolayı denetler. En az bir basamak bir küçük harf, bir büyük harf 
          // ve 8 ile 10 karakter uzunluğunda olmalı kontrolü.
          if ( !Regex.IsMatch(passwordTxt.Text, 
                            @"^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$" ))
            throw new FormatException("Invalid password format");
      }
      
      
    •     Parametreleri Store Procedure'lar olarak kullanın. Sadece Store Procedureları 
      kullanmak, Sql enjeksiyonunu engellemez. Yapılması gereken en önemli şey saklı 
      yordamlarla parametreleri kullanmaktır. Parametreleri kullanmazsanız, saklanan
      prosedürleriniz, başta açıklandığı gibi filtrelenmemiş girdi kullanıyorsa enjeksiyonuna
      duyarlı olabilir. Aşağıdaki kod, bir saklı yordamı çağırırken  SqlParameterCollection'ın
      nasıl kullanılacağını gösterir.
      
          ÖR:
      
      using (SqlConnection connection = new SqlConnection(connectionString)) { DataSet userDataset = new DataSet(); SqlDataAdapter myCommand = new SqlDataAdapter( "LoginStoredProcedure", connection); myCommand.SelectCommand.CommandType = CommandType.StoredProcedure; myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text; myCommand.Fill(userDataset); }
      
          Bu durumda, @au_id parametresi çalıştırılabilir kod değil, bir gerçek değer olarak kabul edilir. Ayrıca, parametre tip ve uzunluk bakımından kontrol edilir. Önceki kod örneğinde, giriş değeri 11 karakterden uzun olamazdı. Veriler, parametre tarafından tanımlanan türe veya uzunluğa uymazsa, SqlParameter sınıfı bir istisna atar.
    • Dinamik SQL ile Parametreleri Kullanın. Saklı yordamları kullanamazsanız, dinamik Sql sorguları oluştururken yine de parametreleri kullanmanız gerekir. Aşağıdaki kod, SqlParametersCollection'ın dinamik Sql ile nasıl kullanılacağını göstermektedir. ÖR:
      using (SqlConnection connection = new SqlConnection(connectionString))
      {
        DataSet userDataset = new DataSet();
        SqlDataAdapter myDataAdapter = new SqlDataAdapter(
               "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", 
               connection);                
        myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
        myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
        myDataAdapter.Fill(userDataset);
      }
    • EK HUSUSLAR
      
    1. Özel girdi karakterlerini işlemek için kaçış yordamlarını kullanın.
    2. En az ayrıcalıklı bir veritabanı hesabı kullanın.
    3. Hata bilgisini açıklamaktan kaçının.
        Elimden geldiğince sizler için güzel bir açıklama olmasına gayret gösterdim, Umarım faydalı olmuştur hepinize. Ayrıca bu saldıları test etmek isterseniz, lütfen merak edip siteler üzerinde değil, hali hazırda üzerinde bu açıkların var olduğu ve test etmeniz için yaratılan hackertest.net sitesini kullanın lütfen arkadaşlar, güvenli kalın ! :)

    Kaynakça:

        1) http://vera.cd/2vwDtCD

        2) http://bit.ly/2vboywO

        3) https://tr.wikipedia.org/wiki/SQL_Injection
     
        4) https://msdn.microsoft.com/en-us/library/ff648339.aspx

        5) https://www.owasp.org/index.php/SQL_Injection

        6) https://www.w3schools.com/sql/sql_injection.asp

        7) http://e-bergi.com/y/SQL-injection

        8) https://www.owasp.org/index.php/Blind_SQL_Injection

        9) https://www.bgasecurity.com/makaleler/

    Yorumlar