Saklı yordam içinde bu sorguda SQL Injection neden gerçekleşmiyor?


18

Aşağıdaki saklı yordamı yaptım:

ALTER PROCEDURE usp_actorBirthdays (@nameString nvarchar(100), @actorgender nvarchar(100))
AS
SELECT ActorDOB, ActorName FROM tblActor
WHERE ActorName LIKE '%' + @nameString + '%'
AND ActorGender = @actorgender

Şimdi böyle bir şey yapmayı denedim. Belki bu yanlış yapıyorum, ama böyle bir prosedür herhangi bir SQL enjeksiyon önleyebilir emin olmak istiyorum:

EXEC usp_actorBirthdays 'Tom', 'Male; DROP TABLE tblActor'

Aşağıdaki resim, yukarıdaki SQL'in SSMS'de yürütüldüğünü ve sonuçların bir hata yerine doğru şekilde görüntülendiğini göstermektedir:

resim açıklamasını buraya girin

Btw, sorgu yürütüldükten sonra noktalı virgülün ardından bu bölümü ekledim. Sonra tekrar çalıştırdım, ama tblActor tablosunun var olup olmadığını kontrol ettiğimde hala oradaydı. Yanlış bir şey mi yapıyorum? Yoksa bu gerçekten enjeksiyon geçirmez mi? Sanırım burada sormaya çalıştığım şey de bu gibi saklı bir yordam mı? Teşekkür ederim.


Bunu denediniz miEXEC usp_actorBirthdays 'Tom', 'Male''; DROP TABLE tblActor'
MarmiK

Yanıtlar:


38

Bu kod şu şekilde düzgün çalışıyor:

  1. Parametreli ve
  2. Değil herhangi Dinamik SQL yapıyor

İşe SQL Enjeksiyon için, size (yapmadığınız) bir sorgu dizesi oluşturmak ve gerek olmayan çevirmek tek kesme ( 'kaçarak-kesme işareti içine) ( '') (bu giriş parametreleri aracılığıyla öncelenir).

"Güvenliği ihlal edilmiş" bir değeri aktarmaya çalıştığınızda, 'Male; DROP TABLE tblActor'dize tam da budur.

Şimdi, eğer şu çizgilerle bir şeyler yapıyorsanız:

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'SELECT fields FROM table WHERE field23 = '
          + @InputParam;

EXEC(@SQL);

Sonra o çünkü SQL Enjeksiyon duyarlı olacağını o sorgu akımı, önceden çözümlü bağlam içinde değildir; bu sorgu şu anda başka bir dizedir. Yani değeri @InputParamolabilir '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;ve bu bir sorun oluşturabilir, çünkü bu sorgu şu şekilde işlenir ve yürütülür:

SELECT fields FROM table WHERE field23 = '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;

Bu, Saklı Yordamları kullanmanın başlıca nedenlerinden biridir: doğal olarak daha güvenlidir (kullanılan parametrelerin değerlerini doğrulamadan yukarıda gösterdiğim gibi sorgular oluşturarak bu güvenliği atlatmazsanız). Dinamik SQL oluşturmanız gerekiyorsa, tercih edilen yol bunu kullanarak parametrelendirmektir sp_executesql:

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'SELECT fields FROM table WHERE field23 = @SomeDate_tmp';

EXEC sp_executesql
  @SQL,
  N'SomeDate_tmp DATETIME',
  @SomeDate_tmp = @InputParam;

Bu yaklaşımı kullanarak, '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;bir DATETIMEgiriş parametresi için geçmeye çalışan biri Saklı Yordam yürütülürken hata alır. Veya Saklı Yordam kabul bile @InputParameterolarak NVARCHAR(100), bir karşı dönüştürmek zorunda kalacak DATETIMEo içine geçmek için sp_executesqlçağrı. Ve Dinamik SQL'deki parametre bir dize türü olsa bile, en başta Saklı Yordam'a gelen herhangi bir tek kesme işareti otomatik olarak çift kesme işaretine kaçar.

Saldırganın giriş alanını kesme işaretleriyle doldurmaya çalıştığı daha az bilinen bir saldırı türü vardır, böylece Saklı Yordamın içindeki Dinamik SQL'i oluşturmak için kullanılacak ancak çok küçük olduğu bildirilen bir şey her şeye sığmaz ve bitiş kesme işaretini dışarı iter ve dizgide artık "kaçmayacak" şekilde bir şekilde doğru kesme işareti ile biter. Buna SQL Truncation denir ve Bala Neerumalla tarafından "Yeni SQL Truncation Saldırıları ve Onlardan Nasıl Korunur" başlıklı bir MSDN dergisinde bahsedildi, ancak makale artık çevrimiçi değil. Bu makaleyi içeren sorun - MSDN Magazine'in Kasım 2006 sürümü - yalnızca Windows Yardım dosyası ( .chm biçiminde) olarak kullanılabilirbiçim). İndirirseniz, varsayılan güvenlik ayarları nedeniyle açılmayabilir. Bu durumda, MSDNMagazineNovember2006en-us.chm dosyasına sağ tıklayın ve "Özellikler" i seçin. Bu sekmelerden birinde, kontrol edilmesi / etkinleştirilmesi gereken "Bu dosya türüne güven" (veya bunun gibi bir şey) seçeneği bulunur. "Tamam" düğmesini tıklatın ve sonra .chm dosyasını yeniden açmayı deneyin .

Truncation saldırısının bir başka varyasyonu, yerel değişkenin "güvenli" kullanıcı tarafından sağlanan değeri saklamak için kullanıldığını varsayarsak, kaçmak için herhangi bir tek tırnak bulunduğundan, bu yerel değişkeni doldurmak ve tek tırnak koymak sonunda. Buradaki fikir, yerel değişken düzgün bir şekilde boyutlandırılmadıysa, sonunda ikinci tek tırnak için yeterli alan kalmayacağı, değişkeni tek bir tırnak ile biten ve ardından tek tırnak ile birleştiren Dinamik SQL'deki değişmez değeri sonlandırır ve bu biten tek tırnak işaretini gömülü bir tek tırnak içine dönüştürür ve Dinamik SQL'deki dize değişmez değeri, bir sonraki dize değişmezine başlaması amaçlanan bir sonraki tek tırnakla biter. Örneğin:

-- Parameters:
DECLARE @UserID      INT = 37,
        @NewPassword NVARCHAR(15) = N'Any Value ....''',
        @OldPassword NVARCHAR(15) = N';Injected SQL--';

-- Stored Proc:
DECLARE @SQL NVARCHAR(MAX),
        @NewPassword_fixed NVARCHAR(15) = REPLACE(@NewPassword, N'''', N''''''),
        @OldPassword_fixed NVARCHAR(15) = REPLACE(@OldPassword, N'''', N'''''');

SELECT @NewPassword AS [@NewPassword],
       REPLACE(@NewPassword, N'''', N'''''') AS [REPLACE output],
       @NewPassword_fixed AS [@NewPassword_fixed];
/*
@NewPassword          REPLACE output          @NewPassword_fixed
Any Value ....'       Any Value ....''        Any Value ....'
*/

SELECT @OldPassword AS [@OldPassword],
       REPLACE(@OldPassword, N'''', N'''''') AS [REPLACE output],
       @OldPassword_fixed AS [@OldPassword_fixed];
/*
@OldPassword          REPLACE output          @OldPassword_fixed
;Injected SQL--       ;Injected SQL--         ;Injected SQL--
*/

SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
           + @NewPassword_fixed + N''' WHERE [TableNameID] = '
           + CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
           + @OldPassword_fixed + N''';';

SELECT @SQL AS [Injected];

Burada, yürütülecek Dinamik SQL şu şekildedir:

UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';

Aynı Dinamik SQL, daha okunabilir bir biçimde:

UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';

Injected SQL--';

Bunu düzeltmek kolaydır. Sadece aşağıdakilerden birini yapın:

  1. DİNAMİK SQL KESİNLİKLE KESİNLİKLE GEREKLİ OLMAYIN! (Bunu ilk olarak listeliyorum çünkü gerçekten dikkate alınması gereken ilk şey olmalı).
  2. Yerel değişkenin uygun şekilde boyutlandırılması (yani, geçirilen tüm karakterlerin tek tırnak olması durumunda, girdi parametresinin iki katı boyutta olması gerekir.
  3. "Sabit" değeri depolamak için yerel bir değişken kullanmayın; REPLACE()doğrudan Dinamik SQL'in oluşturulmasına koymanız yeterlidir:

    SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
               + REPLACE(@NewPassword, N'''', N'''''') + N''' WHERE [TableNameID] = '
               + CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
               + REPLACE(@OldPassword, N'''', N'''''') + N''';';
    
    SELECT @SQL AS [No SQL Injection here];

    Dinamik SQL'den artık ödün verilmiyor:

    UPDATE dbo.TableName SET [Password] = N'Any Value ....''' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';

Yukarıdaki Trunction örneği hakkında notlar:

  1. Evet, bu çok tartışmalı bir örnek. Enjekte etmek için sadece 15 karakterde yapılabilecek çok şey yok. Elbette, a DELETE tableNameyıkıcı olabilir, ancak arka kapı kullanıcısı ekleme veya yönetici şifresini değiştirme olasılığı daha düşüktür.
  2. Bu tür bir saldırı muhtemelen kod, tablo adları vb. Hakkında bilgi gerektirir. Rastgele yabancı / script-kiddie tarafından yapılması daha az olasıdır, ancak bir güvenlik açığı bilen oldukça üzgün eski bir çalışanın saldırdığı bir yerde çalıştım. Kimsenin farkında olmadığı belirli bir web sayfasında. Yani, bazen saldırganlar sistem hakkında samimi bilgiye sahip olurlar.
  3. Elbette, herkesin şifresini sıfırlamanın araştırılması muhtemeldir, bu da şirketi bir saldırı olduğunu iddia edebilir, ancak yine de arka kapı kullanıcısına enjekte etmek veya daha sonra kullanmak / kullanmak için ikincil bilgi almak için yeterli zaman sağlayabilir.
  4. Bu senaryo çoğunlukla akademik olsa bile (yani gerçek dünyada olması muhtemel değildir), yine de imkansız değildir.

SQL Injection ile ilgili daha ayrıntılı bilgi için (çeşitli RDBMS ve senaryoları kapsar), lütfen Açık Web Uygulaması Güvenlik Projesi'nden (OWASP) aşağıdakilere bakın :
SQL Injection Testi

İlgili Enjeksiyon Taşması SQL Enjeksiyonu ve SQL Truncation cevabı:
'kaçış karakterini değiştirdikten sonra T-SQL ne kadar güvenli?


2
Oh, çok teşekkür ederim, bu harika bir cevap. Şimdi anlıyorum. Sonunda bahsettiğiniz tekniği, saldırganın giriş alanını kesme işaretleri ile doldurmaya çalıştığı yerde de görmek isterim, eğer bulabilirseniz. Şimdiden teşekkürler. Bunu açık tutacağım, eğer bulamazsan, bunu cevap olarak seçeceğim.
Ravi

1
@Ravi Bağlantıyı buldum ancak artık arşivlendikleri için makaleye ulaşmıyor. Ancak bazı bilgiler ve yararlı bağlantılar ekledim ve hala bu arşivlerde makaleyi bulmaya çalışıyorum.
Solomon Rutzky

1
Teşekkür ederim srutzsky, OWASP makalesini ve enjeksiyon testlerini okuyacağım. Doğru hatırlıyorsam, güvenlik testi için savunmasız web uygulaması olan 'mutillidae', üniversitede 'OR 1 = 1' dizesiyle yaptığım SQL enjeksiyonuna sahip, bu da mutillidae'de yönetici olarak web uygulamasına giriş yapmama neden oldu. düşünüyorum. İşte o zaman SQL enjeksiyonuyla ilk tanıştım.
Ravi

1
Ben de .chm dosyasını görüntüleyemiyorum, ancak bu mükemmel cevap ve stackoverflow gelen ve OWASP gelen de dahil olmak üzere tüm yararlı bağlantılar için teşekkür ederiz. Bugün okudum ve bundan çok şey öğrendim.
Ravi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.