Parametre bir dizge olmadığında bir SQL sorgusunu parametreleştirmemek güvenli midir?


113

SQL enjeksiyonu açısından, bir stringparametreyi parametreleştirmenin gerekliliğini tamamen anlıyorum ; bu, kitaptaki en eski numaralardan biridir. Ama ne zaman için haklı olabilir değil bir parameterize SqlCommand? Herhangi bir veri türü parametreleştirmemek için "güvenli" kabul ediliyor mu?

Örneğin: Kendimi bir SQL uzmanının yakınında görmüyorum , ancak bir boolveya intbir'yi kabul edip doğrudan sorguya eklemenin SQL enjeksiyonuna karşı potansiyel olarak savunmasız olacağı herhangi bir durum düşünemiyorum .

Varsayımım doğru mu yoksa bu, programımda büyük bir güvenlik açığı bırakabilir mi?

Açıklama için bu soru etiketlenmiştir türü kesin belirlenmiş bir dil olan; "parametre" dediğimde, şöyle bir şey düşün public int Query(int id) .


14
Parametreleri kullanmazsanız önbelleğe alınmış sorgu planlarından yararlanamazsınız, sağladığınız her yeni girdi kombinasyonu için ayrı bir sorgu planı yapmanız gerekir.
Scott Chamberlain

5
@MatthewWhited Daha az zaman alacağını nasıl anlarsınız? Bu durum, mevcut bir geliştiriciden ve önceki geliştiriciden belirli projelerde her yerde ortaya çıkar. Güvenliği gerçekten artırıyorsa, lütfen bir yanıt gönderin. Açıklık getirmek için, açıkça parametreleştirmenin daha iyi olduğuna katılıyorum. Ama bu gerçekten benim sorum değil.
johnnyRose

7
Parametreli sorgular, öncelikle performans ve optimizasyon için kullanılır. SQL enjeksiyonu önleme bir yan etkidir.
Salman

13
Bence OP geçerli bir soru sordu. Potansiyel bir riski düzeltmenin maliyetini / faydasını değerlendirmeye çalışıyor. denklem, bu riskin potansiyeline göre değişir. sıfır risk varsa ben de yapmam. Potansiyel hakkında teknik bir soru sordu, zamanına değip değmediğini düşündüğünüzün öznel yargısı için değil. OP, bu aramayı yapabilecek tek kişidir.
Sir Swears-a-lot

10
Kendimi açıklamak gerekirse: Ben bir dba'yım. En iyi uygulamayı takdir ediyorum ve saygı duyuyorum ve mükemmel bir dünyada tüm kodlar mükemmel olurdu. Ne yazık ki, içinde çalıştığım dünyada, çözmek için zamanımdan daha çok çözmem gereken sorun var. Bu, önceliklendirme demektir. Zaten çalışan, güvenli ve kabul edilebilir seviyelerde performans gösteren IMO Yeniden Yazma kodu bir lüks gibi görünüyor. (
Ödeyemeyeceğim

Yanıtlar:


101

Sanırım güvenli ... teknik olarak , ama içine girmek çok kötü bir alışkanlık. Gerçekten böyle sorgular yazmak istiyor musun?

var sqlCommand = new SqlCommand("SELECT * FROM People WHERE IsAlive = " + isAlive + 
" AND FirstName = @firstName");

sqlCommand.Parameters.AddWithValue("firstName", "Rob");

Ayrıca, bir türün tam sayıdan dizeye değişmesi durumunda da sizi savunmasız bırakır (adına rağmen harf içerebilen çalışan numarasını düşünün).

Yani, biz gelen ÇalışanNo tipini değiştirdik intiçin string, ama bizim sql sorguları güncellemek için unuttum. Hata.


24
AddWithValue Şimdiden kullanmayı bırakabilir miyiz ? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
RemarkLima

5
@RemarkLima Değerleri parametrelere eşleyen kodu dinamik olarak oluştururken çözüm nedir? Blog yazısı bu senaryoyu ele almıyor. Evet, bilindiğinde SQL türünü ayarlamak için tek bir satırdır , ancak olmadığında bir sorununuz olur (veya bu bilgilerle modellere açıklama eklemeye başvurmanız gerekir).
casperOne

1
O zaman AddWithValue, ifadenin dinamik yapısının bir parçası olarak veritabanı türlerinin bir eşlemesine sahip değilseniz, takılıp kalırsınız. Hedef sütunların bir listesine sahip olduğunuzu ve sözlüğün bir parçası olarak, isterseniz türlere sahip olabileceğinizi varsayıyorum. Aksi takdirde, performans vuruşunu yakalayın. Sonuçta, düşündüğümü bilmek iyi bir bilgi.
RemarkLima

8
@RemarkLima " AddWithValueŞimdiden kullanmayı bırakabilir miyiz ?" türü biliyorsanız, kullanmaktan kaçınmalısınız AddWithValue.
casperOne

2
Hey, haberciyi vurma, ben yazmadım ;-) ama konu kalır ve eğer tasarımlarınıza baştan dahil edilmişse, türünü bilmemeniz için hiçbir neden yok. En iyi uygulama ve tüm bu caz :-)
RemarkLima

65

Eğer (bir web sunucusu gibi) kontrol bilgisayarda özellikle yazılan platformunu kullanarak, yalnızca getiren sorgular için yerleştirilen kodu önleyebilir bool, DateTimeveya int(ve diğer sayısal) değerler. Sorun, sql sunucusunu her sorguyu yeniden derlemeye zorlamak ve hangi sorguların hangi sıklıkta çalıştırıldığına dair (önbellek yönetimine zarar veren) iyi istatistikler almasını engelleyerek ortaya çıkan performans sorunlarıdır.

Ancak bu "kontrol ettiğiniz bir bilgisayarda" kısmı önemlidir, çünkü aksi takdirde bir kullanıcı sistem tarafından bu değerlerden dizeler oluşturmak için kullanılan davranışı rastgele metin içerecek şekilde değiştirebilir.

Uzun vadeli düşünmeyi de seviyorum. Günümüzün eski ve bozulmuş güçlü yazılmış kod tabanı, yeni dinamik diline otomatik çeviri yoluyla taşındığında ve aniden tür denetimini kaybederseniz, ancak dinamik kod için henüz tüm doğru birim testlerine sahip değilseniz ne olur? ?

Gerçekten, bu değerler için sorgu parametreleri kullanmamak için iyi bir neden yoktur. Bunu yapmanın doğru yolu bu. Devam edin ve değerleri gerçekten sabit olduklarında sql dizesine sabit kodlayın, ancak aksi halde neden sadece bir parametre kullanılmasın? Zor değil gibi.

Nihayetinde, ben buna böcek demezdim, ama ben buna koku derdim : kendi başına bir hatadan çok az düşen bir şey, ancak böceklerin yakında olduğunun veya eninde sonunda olacağının güçlü bir göstergesi. İyi kod, koku bırakmayı önler ve herhangi bir iyi statik analiz aracı bunu işaretler.

Bunun maalesef doğrudan kazanabileceğiniz türden bir tartışma olmadığını da ekleyeceğim. "Doğru" olmanın artık yeterli olmadığı bir durum gibi görünüyor ve bu sorunu kendi başınıza çözmek için iş arkadaşlarınızın ayak parmaklarına basmanız, muhtemelen iyi ekip dinamiklerini teşvik etmeyecek; sonuçta yardım ettiğinden daha fazla acıtabilir. Bu durumda daha iyi bir yaklaşım, statik bir analiz aracının kullanımını teşvik etmek olabilir. Bu, hedeflenen ve geriye giden çabalara ve mevcut kodu düzeltmeye meşruiyet ve güvenilirlik sağlayacaktır.


1
Bunu parametreleştirmek kesinlikle zor değil. Sorum, bir iş arkadaşımın tamsayı değerlerini birleştiren bir dizi sorgu yazması nedeniyle ortaya çıktı ve hepsini gözden geçirip düzeltmenin zaman kaybı olup olmadığını merak ediyordum.
johnnyRose

2
Sanırım "Bu bir hata mı?"
johnnyRose

7
Bu bir "koku": kendi başına bir böcek olmaktan çıkan bir şeydir, ancak böceklerin muhtemelen yakında olduğunu gösterir. İyi kod, kokuları gidermeye çalışır. Herhangi bir iyi statik analiz aracı kesinlikle onu işaretler.
Joel Coehoorn

1
"Koku" terimini seviyorum. Bunun yerine "larva" gibi bir şey kullanırdım, ancak henüz tam bir hata değil, ancak gelecekteki güncellemeler, siz onu ezene veya fümigasyona uğratana kadar arka ucunuzda yiyecek bir kurtçuk için yakalayabilir. Nekrotik kod potansiyelinin bir üretim ortamında ortaya çıkmasını kesinlikle istemezsiniz ve belirli bir düzeyde ustalıkla geliştirilmemiş bir şeye sahip olmak, bu durumda olduğu gibi kesinlikle var olmasına neden olabilir.
CSS

1
Bu çok yanlış. DateTimeVeya ile nasıl hala SQL enjeksiyonu oluşturabileceğinize dair int
cevabıma bakın

53

Bazı durumlarda, dize değerleri dışındaki parametreleştirilmemiş (birleştirilmiş) değişkenlerle SQL enjeksiyon saldırısı gerçekleştirmek mümkündür - Jon'un bu makalesine bakın: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -kültür / .

Mesele şu ki ToString, bazı özel kültür sağlayıcıları, dize olmayan bir parametreyi, sorguya bir miktar SQL enjekte eden dize temsiline dönüştürebilir.


14
Bence bu, esasen " intS ile enjeksiyon nasıl mümkün olabilir ?" Sorusuna cevap veren tek gönderi.
Arturo Torres Sánchez

3
Yine de, bubi tuzağı gibi özel kodu enjekte edecek bir konumdaysanız, CultureInfoyine de neden SQL enjeksiyonuna ihtiyacınız olduğunu bilmek zor.
Martin Smith

artı 1, o tek cevap aslında cevaplar soru
ken2k

@MartinSmith: CultureInfo'yu dışarıdan değiştirmenin olası bir yolunu gösteren cevabıma bakın.
user1027167

Bir kişi uygulamada böyle bir kod yazabiliyorsa neden SQL Enjeksiyonuna ihtiyaç duyar?
Rıza Aghaei

51

Bu, dize olmayan türler için bile güvenli değildir . Her zaman parametreleri kullanın. Dönemi.

Aşağıdaki kod örneğini düşünün:

var utcNow = DateTime.UtcNow;
var sqlCommand = new SqlCommand("SELECT * FROM People WHERE created_on <= '" + utcNow + "'");

İlk bakışta kod güvenli görünüyor, ancak Windows Bölgesel Ayarlarında bazı değişiklikler yaparsanız ve kısa tarih biçiminde enjeksiyon eklerseniz her şey değişir:

Datetime Enjeksiyonu

Şimdi ortaya çıkan komut metni şöyle görünür:

SELECT * FROM People WHERE created_on <= '26.09.2015' OR '1'<>' 21:21:43'

intKullanıcı, kolayca SQL enjeksiyonuna dönüştürülebilen özel negatif işareti tanımlayabildiğinden , aynısı tür için de yapılabilir .

Değişmez kültürün mevcut kültür yerine kullanılması gerektiği tartışılabilir, ancak bunun gibi dizgi birleştirme işlemlerini pek çok kez gördüm ve +. Kullanarak dizeleri nesnelerle birleştirirken gözden kaçırmak oldukça kolaydır .


10
Sunucu ayarlarını kim değiştirebilir? Bir kişi bunu sunucunuzda yapabiliyorsa, verileri yok etmek için SQL Enjeksiyonuna ihtiyacı yoktur.
Rıza Aghaei

5
Bu en iyi cevap, OP'lerin bunun bir hata / güvenlik açığı olduğu endişesini doğrulamanın bir yolunu gösteriyor. Örneğin, SQL'de veri zamanlarını birleştirmenin yanı sıra performans ve geleceğe yönelik provizyon, yalnızca bir koku veya teknoloji borcu değildir . @RezaAghaei'nin sorusu Sunucu Tarafından hiç bahsetmedi, SQLExpress içeren bir Windows Uygulaması olabilir - her iki durumda da bu soru için kriter değildir. Herkesin söyleyebileceği gibi, bu mükemmel yanıtı çürütmek için sunucu ayarlarına erişimi olan, tıpkı herkesin paylaşılan sunucu barındırma veya Y2K hatası hakkında ne söyleyebileceği gibi. Sunucunun kilitlendiğine katılıyorum - bu sadece bir ön koşul değil.
Jeremy Thompson

2
intTip hakkında söylediklerinize bir örnek verebilir misiniz ?
johnnyRose

1
Bunu yanıtladığınızdan bu yana birkaç hafta geçtiğini biliyorum, ancak gönderinizi düzenlemeniz ve özel bir eksi işaretini nasıl tanımlayabileceğinize dair bir örnek eklemeniz mümkün olabilir mi?
johnnyRose

23

"SELECT * From Table1 WHERE Id =" + intVariable.ToString ()


Güvenlik
Tamam.
Saldırganlar, yazdığınız int değişkenine hiçbir şey enjekte edemezler.

Performans
Tamam Değil.

Parametreleri kullanmak daha iyidir, bu nedenle sorgu bir kez derlenecek ve bir sonraki kullanım için önbelleğe alınacaktır. Bir dahaki sefere farklı parametre değerleriyle bile, sorgu önbelleğe alınır ve veritabanı sunucusunda derlenmesine gerek yoktur.

Kodlama Stili
Kötü uygulama.

  • Parametreler daha okunabilir
  • Belki de parametresiz sorgulara alışmanıza neden olur, o zaman belki bir kez hata yaptınız ve bu şekilde bir dize değeri kullandınız ve muhtemelen verilerinize veda etmelisiniz. Kötü alışkanlık!


"SEÇİN * Ürün WHERE Id =" + TextBox1.Text


Sorunuz olmasa da gelecekteki okuyucular için yararlı olabilir:

Güvenlik
Felaketi! Alan tam sayı
olsa bile Id, sorgunuz SQL Enjeksiyonuna tabi olabilir. Uygulamanızda bir sorgunuz olduğunu varsayalım "SELECT * FROM Table1 WHERE Id=" + TextBox1.Text, Bir saldırgan metin kutusuna ekleyebilir 1; DELETE Table1ve sorgu şöyle olur:

"SELECT * FROM Table1 WHERE Id=1; DELETE Table1"

Burada parametrize sorgu kullanmak istemiyorsanız, yazılan değerleri kullanmalısınız:

string.Format("SELECT * FROM Table1 WHERE Id={0}", int.Parse(TextBox1.Text))


Senin sorun


Sorum, bir iş arkadaşımın tamsayı değerlerini birleştiren bir dizi sorgu yazması nedeniyle ortaya çıktı ve hepsini gözden geçirip düzeltmenin zaman kaybı olup olmadığını merak ediyordum.

Bu kodları değiştirmenin zaman kaybı olmadığını düşünüyorum. Gerçekten de değişiklik Önerilir!

iş arkadaşınız int değişkenleri kullanıyorsa, güvenlik riski yoktur, ancak bu kodları değiştirmek zaman kaybı değildir ve gerçekten de bu kodları değiştirmeniz önerilir. Kodu daha okunabilir, daha sürdürülebilir hale getirir ve yürütmeyi daha hızlı hale getirir.


İlk seçenek bile güvenlik için tamamen uygun değildir. Davranışı, .ToString()rasgele metin içerecek şekilde değiştirilmesi kolay bir işletim sistemi yapılandırma öğesi tarafından belirlenir.
Joel Coehoorn

18

Aslında birinde iki soru var. Başlıktan gelen sorunun, OP'nin daha sonra yorumlarda ifade ettiği endişelerle çok az ilgisi var.

Google'dan gelen okuyucular için önemli olanın OP için özel durum olduğunu fark etsem de, daha genel bir soruya cevap vermenin önemli olduğunu, "emin yaptıysam hazırlanmış ifadeler kadar güvenli birleştirme" şeklinde ifade edilebilir. birleştirdiğim her kelimenin tam anlamıyla güvenli olduğunu? " Bu nedenle, bu ikincisine konsantre olmak istiyorum. Ve cevap

Kesinlikle hayır.

Açıklama çoğu okuyucunun istediği kadar doğrudan değil, ama elimden gelenin en iyisini yapacağım.

Bir süredir konu üzerine kafa yoruyordum ve sonuçta her şeyi özetlemeye çalıştığım makale (PHP ortamına dayanıyor olsa da) ortaya çıktı. SQL enjeksiyonundan korunma sorununun genellikle dizgi kaçışı, tür atama ve benzeri gibi bazı ilgili ancak daha dar konulara doğru kaçtığı aklıma geldi. Bazı önlemler kendi başlarına alındığında güvenli kabul edilebilecekse de, hiçbir sistem veya izlenecek basit bir kural yoktur. Bu da zemini çok kaygan hale getiriyor, geliştiricinin dikkatini ve deneyimini çok fazla yüklüyor.

SQL enjeksiyonu sorunu belirli bir sözdizimi sorununa göre basitleştirilemez. Ortalama bir geliştiricinin düşündüğünden daha geniştir. Bu aynı zamanda metodolojik bir soru. Bu sadece "hangi biçimlendirmeyi uygulamamız gerektiği" değil, aynı zamanda " nasıl yapılmalı" dır .

(Bu bakış açısına göre, Jon Skeet'in diğer yanıtta atıfta bulunduğu bir makale iyiden çok kötü gidiyor, çünkü yine bazı uç durumlara odaklanıyor, belirli bir sözdizimi sorununa yoğunlaşıyor ve sorunu bütünüyle ele alamıyor.)

Koruma sorununu bir bütün olarak değil, bir dizi farklı sözdizimi sorunu olarak ele almaya çalıştığınızda, çok sayıda sorunla karşı karşıya kalırsınız.

  • olası biçimlendirme seçenekleri listesi gerçekten çok büyük. Birinin bazılarını kolayca gözden kaçırabileceği anlamına gelir. Veya onları karıştırın ( örneğin , tanımlayıcı için dize kaçışını kullanarak ).
  • Birleştirme, tüm koruma önlemlerinin program tarafından değil programcı tarafından yapılması gerektiği anlamına gelir. Bu sorun tek başına birkaç sonuca yol açar:
    • böyle bir biçimlendirme manueldir. Manuel, son derece hataya açık demektir . Kişi başvurmayı unutabilir.
    • dahası, biçimlendirme prosedürlerini merkezileştirilmiş bir işleve taşımak, işleri daha da karıştırmak ve veritabanına gitmeyen verileri bozmak için bir cazibe vardır.
  • birden fazla geliştirici söz konusu olduğunda, sorunlar on katına çıkar.
  • birleştirme kullanıldığında, potansiyel olarak tehlikeli bir sorguya bir bakışta söylenemez: hepsi potansiyel olarak tehlikeli!

Bu karışıklığın aksine, hazırlanmış ifadeler gerçekten Kutsal Kase'dir:

  • takip edilmesi kolay basit bir kural şeklinde ifade edilebilir.
  • esasen ulaşılamaz bir önlemdir, yani geliştiricinin müdahale edemeyeceği ve isteyerek veya istemeyerek süreci bozamayacağı anlamına gelir.
  • Enjeksiyondan korunma, gerçekte hazırlanmış ifadelerin yalnızca bir yan etkisidir ve gerçek amaç sözdizimsel olarak doğru ifadeler üretmektir. Ve sözdizimsel olarak doğru bir ifade% 100 enjeksiyon kanıtıdır. Yine de herhangi bir enjeksiyon olasılığına rağmen sözdizimimizin doğru olmasına ihtiyacımız var.
  • her yerde kullanılırsa, geliştiricinin deneyimine bakılmaksızın uygulamayı korur. Diyelim ki, ikinci dereceden enjeksiyon denen bir şey var . Ve "korumak için, Kullanıcı Tarafından Sağlanan Tüm Girişlerden Kaçın" yazan çok güçlü bir yanılsama . Bir araya geldiklerinde, bir geliştirici karar verme özgürlüğüne sahipse, neyin korunması gerektiğine ve neyin korunmayacağına karar verirse, enjeksiyona yol açar.

(Daha fazla düşündüğümde, mevcut yer tutucu setinin gerçek yaşam ihtiyaçları için yeterli olmadığını ve hem diziler gibi karmaşık veri yapıları hem de bazen eklenmesi gereken SQL anahtar sözcükleri veya tanımlayıcıları için genişletilmesi gerektiğini keşfettim. dinamik olarak da sorgu, ancak bir geliştirici böyle bir durum için silahsız bırakılır ve dize birleştirme işlemine geri dönmek zorunda kalır, ancak bu başka bir sorudur).

İlginç bir şekilde, bu sorunun tartışması, Stack Overflow'un çok tartışmalı doğası tarafından tetikleniyor. Sitenin amacı, aramadan gelen kullanıcılar için uygun genel amaçlı cevaplardan oluşan bir veri tabanına sahip olma hedefine ulaşmak için doğrudan soran kullanıcıların belirli sorularını kullanmaktır . Fikir kendi başına kötü değildir , ancak böyle bir durumda başarısız olur: bir kullanıcı çok dar bir soru sorduğunda , özellikle bir meslektaşıyla bir anlaşmazlıkta bir argüman elde etmek (veya kodu yeniden düzenlemeye değip değmeyeceğine karar vermek). Deneyimli katılımcıların çoğu , misyonu akılda tutarak bir cevap yazmaya çalışırken Yığın Taşması'nın bir bütün olarak ele alınması, yanıtlarının yalnızca OP için değil, mümkün olduğunca çok okuyucu için iyi olmasını sağlar.


10
Soruyu cevaplamıyorum
edc65

Çoğu veritabanı halihazırda kullanılmış, parametreli sorguları SQL dizge eşitliği ile algılar, bu nedenle eski hazırla ve kullan-tutamaç yöntemi benim için modası geçmiş görünüyor. Bu tutamaçlar yalnızca belirli bir kapsam dahilinde kullanılabilir ve tutamacı takip etmek için kodlama gerektirir. Bana göre parametreleştirilmiş sorgular doğrudan kullanılmalıdır, böylece sorgu planları işleme takibi olmadan ve hatta farklı uygulamalarda yeniden kullanılabilir.
Erik Hart

15

Sadece güvenlik veya tür güvenliğiyle ilgili hususları düşünmeyelim.

Parametreleştirilmiş sorguları kullanmanın nedeni, veritabanı düzeyinde performansı artırmaktır. Veritabanı perspektifinden, parametrik bir sorgu SQL tamponundaki bir sorgudur (tüm veritabanlarının dahili olarak benzer bir konsepte sahip olduğunu düşünmeme rağmen Oracle'ın terminolojisini kullanmak için). Böylelikle veri tabanı belirli miktarda sorguyu hafızasında tutabilir, hazırlanmış ve çalışmaya hazır hale getirebilir. Bu sorguların ayrıştırılmasına gerek yoktur ve daha hızlı olacaktır. Sık çalıştırılan sorgular genellikle arabellekte olur ve her kullanıldıklarında ayrıştırılması gerekmez.

SÜRECE

Birisi parametreleştirilmiş sorgular kullanmaz. Bu durumda, ara bellek, her biri veritabanı motoru tarafından ayrıştırılması ve çalıştırılması gereken hemen hemen aynı sorgulardan oluşan bir akışla sürekli olarak temizlenir ve performans, sık çalıştırılan sorgular bile birçok kez yeniden ayrıştırıldığı için her yönden zarar görür. gün. Bir yaşam için veri tabanlarını ayarladım ve bu, az asılı meyvelerin en büyük kaynaklarından biri oldu.

ŞİMDİ

Sorunuzu yanıtlamak için, sorgunuzda az sayıda farklı sayısal değer varsa, büyük olasılıkla sorunlara neden olmazsınız ve aslında performansı sonsuza kadar artırabilirsiniz. Ancak, potansiyel olarak yüzlerce değer varsa ve sorgu çok çağrılırsa, sisteminizin performansını etkileyeceksiniz, bu yüzden yapmayın.

Evet, SQL arabelleğini artırabilirsiniz, ancak bu her zaman sonuçta, Dizinleri veya Verileri önbelleğe almak gibi diğer daha kritik bellek kullanımlarının pahasına olacaktır. Ahlaki, parametreleştirilmiş sorguları oldukça dinsel bir şekilde kullanın, böylece veritabanınızı optimize edebilir ve önemli şeyler için daha fazla sunucu belleği kullanabilirsiniz ...


8

Maciek cevabına biraz bilgi eklemek için:

Derlemenin ana işlevini yansıma yoluyla çağırarak bir .NET üçüncü taraf uygulamasının kültür bilgilerini değiştirmek kolaydır:

using System;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Assembly asm = Assembly.LoadFile(@"C:\BobbysApp.exe");
      MethodInfo mi = asm.GetType("Test").GetMethod("Main");
      mi.Invoke(null, null);
      Console.ReadLine();
    }

    static Program()
    {
      InstallBobbyTablesCulture();
    }

    static void InstallBobbyTablesCulture()
    {
      CultureInfo bobby = (CultureInfo)CultureInfo.InvariantCulture.Clone();
      bobby.DateTimeFormat.ShortDatePattern = @"yyyy-MM-dd'' OR ' '=''";
      bobby.DateTimeFormat.LongTimePattern = "";
      bobby.NumberFormat.NegativeSign = "1 OR 1=1 OR 1=";
      Thread.CurrentThread.CurrentCulture = bobby;
    }
  }
}

Bu yalnızca BobbysApp'ın Ana işlevi herkese açıksa çalışır. Main herkese açık değilse, arayabileceğiniz başka genel işlevler olabilir.


1
Bunu kodla yapmak zorunda bile değilsin. Enjeksiyonu doğrudan Windows Bölgesel Ayarları'ndan ekleyebilirsiniz. Cevabımı gör.
Kaspars Ozols

2
Sunucu ayarlarını kim değiştirebilir veya bu kodu sunucuya kim ovabilir? Bir kişi bunu sunucunuzda yapabiliyorsa, verileri yok etmek için SQL Enjeksiyonuna ihtiyacı yoktur.
Rıza Aghaei

7

Kanımca, çalıştığınız parametrenin hiçbir zaman bir dizge içermeyeceğini garanti edebilirseniz güvenli olur ama ben bunu asla yapmam. Ayrıca, birleştirme gerçekleştirdiğiniz için küçük bir performans düşüşü göreceksiniz. Size soracağım soru, neden parametreleri kullanmak istemiyorsunuz?


1
Parametreleri kullanmak istemediğimden değil, parametreleri kullanıyorum. Bir iş arkadaşım bugün parametreleştirmek için değiştirdiğim böyle bir kod yazdı, bu da soruyu düşünmemi sağladı.
johnnyRose

Tamam. Harika. Parametreleri kullanmak en iyi uygulamadır. Bu şekilde sql injection gibi şeyler için endişelenmenize gerek kalmaz. Ayrıca dinamik sorgular oluşturuyorsanız, sorgularınız ne kadar karmaşık olursa olsun parametreleri de kullanabilirsiniz. Bunları oluştururken @ 1 ... @ n stilini kullanmanız yeterlidir. Ve bunları istenen değerle parametreler koleksiyonuna ekleyin.
Maksimum

@johnyRose Parametreleri kullanmak için bir nokta daha var: programlar gelişiyor ve değişiyor. Birleştirmeyi yalnızca dize için kullanabilirsiniz, ancak bu, birisinin bazı parametre türlerini değiştiren yeniden düzenleme uygulayacağını ve değişikliklerin SQL Enjeksiyon zafiyetine yol açabileceğini garanti etmez.
lerthe61

3

Tamam ama asla güvenli değil .. ve güvenlik her zaman girişlere bağlıdır, örneğin giriş nesnesi TextBox ise saldırganlar, metin kutusu dizeyi kabul edebileceğinden zor bir şey yapabilir, bu nedenle bir tür doğrulama / dönüşüm koymanız gerekir. kullanıcıların yanlış girişi engelleyebilmek. Ama sorun şu ki, bu güvenli değil. Onun kadar basit.


Bu bir dizedir. Tamsayılar, mantıksal değerler veya veri zamanları gibi diğer veri türlerinden bahsediyorum.
johnnyRose

@johnnyRose Yup, yukarıda Kaspards tarafından yanıtlanmış olarak işaretlediğiniz çok güzel bir örnek gördüm .. ve o nadir görülen bir örnek olarak datetime datatipini kullandığı için harika bir yanıt. :) Herhangi bir veri türünde parametre kullanmanın güvenli ve daha iyi olmadığına zaten ikna
olmuşsunuzdur umarım

Parametreleri kullanmanın daha güvenli olduğundan hiç şüphem olmadı. Sorum, türü kesin belirlenmiş uygulamalarla ilgiliydi.
johnnyRose

Evet .. katılıyorum. ve bu da gelecekteki okuyuculara yardımcı olabilecek harika bir soru :)
japzdivino

-2

Hayır, bu şekilde bir SQL enjeksiyon saldırısı alabilirsiniz. Burada nasıl olduğunu gösteren eski bir Türkçe makale yazdım . PHP ve MySQL'de makale örneği ancak konsept C # ve SQL Server'da aynı şekilde çalışır.

Temelde şu şekilde saldırırsınız. Tamsayı id değerine göre bilgileri gösteren bir sayfanız olduğunu düşünelim. Bunu aşağıdaki gibi değer olarak parametrelemediniz.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=24

Tamam, MySQL kullandığınızı varsayıyorum ve şu şekilde saldırıyorum.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII((SELECT%20DATABASE()))

Buraya enjekte edilen değerin dize olmadığını unutmayın. ASCII işlevini kullanarak char değerini int olarak değiştiriyoruz. Aynı şeyi SQL Server'da "CAST (YourVarcharCol AS INT)" kullanarak gerçekleştirebilirsiniz.

Bundan sonra veritabanı adınızı bulmak için uzunluk ve alt dize işlevlerini kullanıyorum.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=LEN((SELECT%20DATABASE()))

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR(SELECT%20DATABASE(),1,1))

Ardından veritabanı adını kullanarak veritabanında tablo adlarını almaya başlarsınız.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR((SELECT table_name FROM INFORMATION_SCHEMA.TABLES LIMIT 1),1,1))

Elbette bu işlemi otomatikleştirmeniz gerekiyor, çünkü sorgu başına yalnızca BİR karakter alıyorsunuz. Ancak bunu kolayca otomatikleştirebilirsiniz. Makalem watir'de bir örnek gösteriyor . Yalnızca bir sayfa kullanmak ve parametreleştirilmiş kimlik değeri kullanmamak. Veritabanınızdaki her tablo adını öğrenebilirim. Bundan sonra önemli tabloları arayabilirim. Zaman alacak ama yapılabilir.


2
Sorum güçlü yazılmış bir dili ifade ediyor. Açıklamanız esnek yazımı olan diller için harika olsa da, enjekte edilen değer hala bir dizedir.
johnnyRose

Enjekte edilen hiçbir değer tamsayı değildir. ASCII MySQL işlevini kullanarak karakter alır ve tam sayıya değiştirirsiniz. Aynı şeyi SQL Server'da CAST (YourCharValue AS INT) kullanarak yaparsınız
Atilla Özgür

Bunun gibi bir şeyi kastetmiştim:public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose

-3

Şey ... kesin olan bir şey var: Güvenlik bir dizeyi (kullanıcı tarafından alınmış) SQL komut dizenizle birleştirdiğinizde OK DEĞİLDİR. Where cümlesinin bir Tamsayıya veya herhangi bir türe atıfta bulunması önemli değildir; enjeksiyonlar meydana gelebilir.

SQL Enjeksiyonunda önemli olan, kullanıcıdan değeri almak için kullanılan değişkenin veri türüdür.

Where cümlesinde bir tam sayıya sahip olduğumuzu varsayarsak ve:

  1. kullanıcı değişkeni bir dizedir. Öyleyse tamam, enjekte etmek (UNION kullanarak) çok kolay değil ama 'OR 1 = 1' benzeri saldırıları kullanarak baypas etmek çok kolay ...

  2. Kullanıcı değişkeni bir tamsayı ise. Daha sonra, sistem çökmeleri için ve hatta gizli bir arabellek taşması için (son dizide) olağandışı büyük sayılar testini geçerek sistemin gücünü 'test edebiliriz' ...;)

Belki sorgular veya (daha iyisi - imo) Depolanan Prosedürlerin parametreleri% 100 Tehdit güvenliği değildir, ancak bunları en aza indirmek için en az gereken (veya tercih ederseniz temel olan) önlemdir.


Sanırım soruyu yanlış anlamışsınızdır. İpli olmayan türlerden bahsediyorum .
johnnyRose

Merhaba JonnyRose ... notunuz için teşekkürler. Sorunuzu anlıyorum, ancak cevabımı daha genel bir şekilde koydum. Dizgisiz durum için lütfen (2) noktamı kontrol edin. ;)
Andreas Venieris
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.