SQL enjeksiyonu, bugün hâlâ çok yaygın olan basit bir saldırı vektörüdür. Bunun sebebi, aptallık için yamaların olmaması. Neden böyle diyorsunuz, JAVA'yı örnek olarak alalım:
Veritabanında böyle bir tablo var olduğunu varsayalım:
Sonra JDBC eylem tablosunu kullanın:
Yukarıdaki kod bazı geliştiriciler tarafından sıkça kullanılır. Gelen userId parametresinin "3; Drop table kullanıcısı; Çalıştırılan SQL ifadesi şöyledir:
Veritabanı deredilip çalıştırıldıktan sonra kullanıcı tablosu silinir. İşte basit bir SQL enjeksiyon saldırısı etkisi oldu! Bunun nedeni, yukarıdaki kodun programlama spesifikasyonlarına uymamasıdır.
Spesifikasyona göre programladığımızda, SQL enjeksiyonu yok. Bu aynı durum da geçerlidirSQL enjeksiyonundan kaçınmanın ilk yolu: önceden derlenmiş ifadeler:, kod şöyledir:
Neden yukarıdaki kodda SQL enjeksiyonu yok? Ön derlenmiş ifade kullanıldığı için, önceden derlenmiş ifade "kullanıcı tarafından ad seç where id= ?" ayarları ayarlıdır. Bu ifade önceden derlenmiş mi, böylece sadece yürütüldüğünde gelen parametrelerle değiştirilmesi yeterli mi? Yer tutucular sorun değil. İlk uyumsuz durumda program bir SQL ifadesi yazar ve ardından kullanıcının ilettiği içerikle derler; bu tam da sorundur.
Önden derlenmiş ilemlerin kullanılmasına ek olarak, ikinci bir seçenek de varSQL enjeksiyon saldırılarından kaçınmanın yolları: Depolanmış prosedürler。 Depolanmış prosedür, belirli bir işlevi yerine getiren, derlenmiş ve veritabanında saklanan SQL ifadeleri kümesidir ve kullanıcı, saklanan bir prosedürü çağırarak ve bir parametre vererek (eğer saklanan prosedürün parametreleri varsa) bunu çalıştırabilir; bu da SQL enjeksiyon saldırılarını önleyebilir
Yukarıdaki kodda ilgili saklanan prosedür şöyledir:
Elbette, kullanıcılar ön uçta karakter kontrolü de yapabilir, bu da SQL enjeksiyonunu önlemenin bir yoludur: örneğin, yukarıdaki userId parametresi için kullanıcı noktalı virgül kontrol eder ve hata görüntülenir. Ancak en temel sebep, SQL enjeksiyon saldırılarının var olmasıdır çünkü uygulamalar veritabanlarına erişerken en az ayrıcalık kullanmaz. Görünüşe göre herkes veritabanına erişmek için kök hesabı kullanıyor.
Peki MyBatis SQL enjeksiyon saldırılarından nasıl kaçınıyor? Ya da yukarıdaki tablo kullanıcısını örnek olarak ele alalım: Diyelim ki haritacı dosyası şöyle:
İlgili java dosyaları şunlardır:
userId="34; Drop table kullanıcısı; Bundan sonra, basılı ifade şöyle deniyor:
Girilen kullanıcı kimliği ne olursa olsun, sql ifadesi şöyle. Bunun nedeni, mybatis'in temel uygulamada önceden derlenmiş ilemler kullanmasıdır. Veritabanı bu ifadeyi çalıştırdığında, doğrudan önceden derlenmiş ifadeyi kullanır ve ardından yer tutucuyu geçen userId ile değiştirir? Sadece koş. Önce yer tutucuları mı değiştirelim? Derleme işlemi yürütülür, bu yüzden SQL enjeksiyonunun hayatta kalması için yer kalmaz.
Peki MyBatis SQL ön derlemesini nasıl yapıyor? Aslında, PreparedStatement sınıfı çerçevenin en altında kullanılır. PreparedStaement sınıfı sadece SQL enjeksiyonunu önlemekle kalmaz, aynı SQL ifadesi N kez çalıştırıldığında (N-1) derleme süresini de azaltır ve böylece verimliliği artırır.
Yukarıdaki ifadeyi şu şekilde değiştirirseniz:
userId="34; Drop table kullanıcısı; Bundan sonra, basılı ifade şöyle deniyor:
Şu anda mybatis önceden derlenmiş ifadeler kullanmaz, önce dizileri birleştirir ve ardından derleme yapar; bu da SQL enjeksiyonunun tam olarak böyle etki yaratmasıdır.
Bu nedenle, mybatis eşleme ifadeleri yazarken "#{xxx}" formatını kullanmaya çalışın. "${xxx}" gibi parametreleri kullanmak zorundaysanız, SQL enjeksiyon saldırılarını önlemek için bunları manuel olarak filtrelemeniz gerekir.
|