PreparedStatements'ın SQL Injection'ı engellediğini / engellediğini biliyorum. Bunu nasıl yapıyor? PreparedStatements kullanılarak oluşturulan son form sorgusu bir dize mi olacak yoksa başka bir şekilde mi olacak?
PreparedStatements'ın SQL Injection'ı engellediğini / engellediğini biliyorum. Bunu nasıl yapıyor? PreparedStatements kullanılarak oluşturulan son form sorgusu bir dize mi olacak yoksa başka bir şekilde mi olacak?
Yanıtlar:
SQL enjeksiyonunun sorunu, bir kullanıcı girdisinin SQL ifadesinin bir parçası olarak kullanılmasıdır. Hazırlanmış ifadeleri kullanarak, kullanıcı girişini bir parametrenin içeriği olarak (SQL komutunun bir parçası olarak değil) işlenmeye zorlayabilirsiniz.
Ancak, kullanıcı girişini hazırlanan ifadeniz için bir parametre olarak kullanmazsanız, bunun yerine SQL komutunuzu dizeleri birleştirerek oluşturursanız, hazırlanmış ifadeleri kullanırken bile SQL enjeksiyonlarına karşı savunmasız kalırsınız .
Aynı şeyi yapmanın iki yolunu düşünün:
PreparedStatement stmt = conn.createStatement("INSERT INTO students VALUES('" + user + "')");
stmt.execute();
Veya
PreparedStatement stmt = conn.prepareStatement("INSERT INTO student VALUES(?)");
stmt.setString(1, user);
stmt.execute();
Kullanıcı girişinden "kullanıcı" gelmişse ve kullanıcı girişi
Robert'); DROP TABLE students; --
Sonra ilk etapta ıslatılacaksın. İkincisi, güvende olursunuz ve Küçük Bobby Tablolar okulunuza kaydolur.
PreparedStatement'ın SQL Enjeksiyonunu nasıl engellediğini anlamak için SQL Sorgusu yürütme aşamalarını anlamamız gerekir.
1. Derleme Aşaması. 2. Yürütme Aşaması.
SQL sunucu motoru bir sorgu aldığında, aşağıdaki aşamalardan geçmek zorundadır,
Ayrıştırma ve Normalleştirme Aşaması: Bu aşamada, Sorgu sözdizimi ve anlambilim açısından kontrol edilir. Sorguda kullanılan referans tablosu ve sütunlarının var olup olmadığını kontrol eder. Aynı zamanda yapacak başka görevleri de var, ancak ayrıntılara girmeyelim.
Derleme Aşaması: Bu aşamada seçme, nereden, nerede vb. Sorgulamada kullanılan anahtar sözcükler makinenin anlayabileceği biçime dönüştürülür. Bu, sorgunun yorumlandığı ve karşılık gelen eyleme karar verildiği aşamadır. Aynı zamanda yapacak başka görevleri de var, ancak ayrıntılara girmeyelim.
Sorgu Optimizasyon Planı: Bu aşamada, sorgunun hangi yollarla yürütülebileceğini bulmak için Karar Ağacı oluşturulur. Sorgunun çalıştırılabileceği yolların sayısını ve Sorgu yürütmenin her bir yolu ile ilişkili maliyeti bulur. Bir sorguyu yürütmek için en iyi planı seçer.
Önbellek: Sorgu optimizasyon planında seçilen en iyi plan önbellekte saklanır, böylece bir dahaki sefere aynı sorgu geldiğinde, Aşama 1, Aşama 2 ve Aşama 3'ten tekrar geçmek zorunda kalmaz. Sorgu bir dahaki sefere geldiğinde, doğrudan Önbellekte kontrol edilecek ve yürütmek için oradan alınacaktır.
Yürütme Aşaması:
Bu aşamada, sağlanan sorgu çalıştırılır ve veriler kullanıcıya döndürülür.ResultSet
nesne .
PreparedStatements eksiksiz SQL sorguları değildir ve çalışma zamanında gerçek kullanıcı tarafından sağlanan verilerle değiştirilen yer tutucular içerir.
Yer tutucular içeren herhangi bir PreparedStatment SQL Server motoruna geçirildiğinde, aşağıdaki aşamalardan geçer.
GÜNCELLEME kullanıcı set kullanıcı adı =? ve şifre =? NEREDE id =?
Yukarıdaki sorgu ayrıştırılır, yer tutucularla birlikte özel işlem olarak derlenir, optimize edilir ve Önbelleğe alınır. Bu aşamada sorgu zaten derlenmiş ve makine tarafından anlaşılabilir bir biçime dönüştürülmüştür. Bu nedenle, önbellekte depolanan Sorgunun Önceden Derlenmiş olduğunu ve yalnızca yer tutucuların kullanıcı tarafından sağlanan verilerle değiştirilmesi gerektiğini söyleyebiliriz.
Artık kullanıcı tarafından sağlanan veriler geldiğinde çalışma zamanında, Ön Derlenmiş Sorgu Önbellekten alınır ve yer tutucular, kullanıcı tarafından sağlanan verilerle değiştirilir.
(Unutmayın, yer tutucular kullanıcı verileriyle değiştirildikten sonra, son sorgu tekrar derlenmez / yorumlanmaz ve SQL Server motoru kullanıcı verilerini, ayrıştırılması veya yeniden derlenmesi gereken bir SQL değil, saf veri olarak görür; PreparedStatement'ın güzelliği budur. )
Sorgunun tekrar derleme aşamasından geçmesi gerekmiyorsa, yer tutucularda değiştirilen veriler saf veri olarak kabul edilir ve SQL Server motoru için hiçbir anlamı yoktur ve sorguyu doğrudan yürütür.
Not: Sorgu yapısını anlayan / yorumlayan ve ona anlamlı davranışlar veren, ayrıştırma aşamasından sonraki derleme aşamasıdır. PreparedStatement durumunda, sorgu yalnızca bir kez derlenir ve önbelleğe alınmış derlenmiş sorgu, kullanıcı verilerini değiştirmek ve yürütmek için her zaman alınır.
PreparedStatement'ın tek seferlik derleme özelliği sayesinde SQL Injection saldırısı içermez.
Örnekle ayrıntılı açıklamayı burada bulabilirsiniz: https://javabypatel.blogspot.com/2015/09/how-prepared-statement-in-java-prevents-sql-injection.html
PreparedStatement içinde kullanılan SQL, sürücüde önceden derlenmiştir. Bu noktadan sonra, parametreler sürücüye SQL'in çalıştırılabilir bölümleri olarak değil, değişmez değerler olarak gönderilir; bu nedenle bir parametre kullanılarak hiçbir SQL enjekte edilemez. PreparedStatements'ın (ön derleme + yalnızca parametreleri gönderme) bir başka yararlı yan etkisi, sürücünün her biri SQL ayrıştırma ve derleme gerçekleştirmesi gerekmediğinden (sürücünün PreparedStatements'ı desteklediği varsayılarak) parametreler için farklı değerlerle bile birden çok kez çalıştırıldığında performans artışıdır parametrelerin değişme zamanı.
Ben tahmin bu bir dize olacaktır. Ancak girdi parametreleri veritabanına gönderilecek ve gerçek bir SQL ifadesi oluşturmadan önce uygun dönüştürme / dönüştürmeler uygulanacaktır.
Size bir örnek vermek gerekirse, CAST / Conversion'ın çalışıp çalışmadığını deneyebilir.
Çalışırsa, ondan nihai bir açıklama yaratabilir.
SELECT * From MyTable WHERE param = CAST('10; DROP TABLE Other' AS varchar(30))
Sayısal bir parametre kabul eden bir SQL ifadesi içeren bir örnek deneyin.
Şimdi, bir dize değişkeni (sayısal parametre olarak kabul edilebilir sayısal içerikle) iletmeyi deneyin. Herhangi bir hata yaratır mı?
Şimdi, bir dize değişkeni geçirmeyi deneyin (sayısal parametre olarak kabul edilemeyen içeriğe sahip). Ne olacağını gördün mü?
Hazırlanan açıklama daha güvenlidir. Bir parametreyi belirtilen türe dönüştürecektir.
Örneğin stmt.setString(1, user);
,user
parametreyi bir String'e .
Parametrenin çalıştırılabilir bir komut içeren bir SQL dizesi içerdiğini varsayalım : hazırlanmış bir ifade kullanmak buna izin vermez.
Buna meta karakter (aka otomatik dönüştürme) ekler.
Bu onu daha güvenli kılar.
SQL enjeksiyonu: kullanıcı, sql ifadesinin parçası olabilecek bir şey girme şansına sahip olduğunda
Örneğin:
Dize sorgusu = "INSERT INTO öğrenciler VALUES ('" + kullanıcı + "')"
kullanıcı "Robert" girdiğinde); DROP TABLE öğrencileri; - "girdi olarak SQL enjeksiyonuna neden olur
Hazırlanmış ifade bunu nasıl engeller?
Dize sorgusu = "INSERT INTO öğrenciler VALUES ('" + ": ad" + "')"
parameters.addValue ("ad", kullanıcı);
=> kullanıcı tekrar girdiğinde "Robert"); DROP TABLE öğrencileri; - ", girdi dizesi sürücüde değişmez değerler olarak önceden derlenmiştir ve sanırım şu şekilde dönüştürülebilir:
CAST ( 'Robert'); DROP TABLE öğrencileri; - 'AS varchar (30))
Yani sonunda, dize tablonun adı olarak kelimenin tam anlamıyla eklenecektir.
http://blog.linguiming.com/index.php/2018/01/10/why-prepared-statement-avoids-sql-injection/
CAST(‘Robert’);
gelen CAST(‘Robert’); DROP TABLE students; –‘ AS varchar(30))
kıracak, o zaman bu durumda olsaydı tablo düşmesi sürdüreceğini belirtti. Enjeksiyonu durdurur, bu yüzden örneğin senaryoyu açıklayacak kadar eksiksiz olmadığına inanıyorum.
PreparedStatement:
1) SQL ifadesinin ön derlemesi ve DB tarafında önbelleğe alınması, genel olarak daha hızlı yürütmeye ve aynı SQL ifadesini toplu işlerde yeniden kullanma becerisine yol açar.
2) Yerleşik alıntılardan ve diğer özel karakterlerden kaçarak SQL enjeksiyon saldırılarının otomatik olarak önlenmesi. Bunun, değeri ayarlamak için PreparedStatement setXxx () yöntemlerinden herhangi birini kullanmanızı gerektirdiğini unutmayın.
Bu yazıda açıklandığı gibi PreparedStatement
, hala Dizeleri birleştiriyorsanız , tek başına size yardımcı olmaz.
Örneğin, bir haydut saldırgan hala aşağıdakileri yapabilir:
Bağlama parametrelerini kullanmıyorsanız yalnızca SQL değil, JPQL veya HQL bile tehlikeye atılabilir.
Sonuç olarak, SQL deyimleri oluştururken asla dize birleştirme kullanmamalısınız. Bu amaç için özel bir API kullanın:
Hazırlanmış İfadelerde, kullanıcı verileri parametre olarak girmeye zorlanır. Kullanıcı DROP TABLE veya SELECT * FROM USERS gibi güvenlik açığından etkilenen bazı ifadeler girerse, bunlar SQL ifadesinin parametreleri olarak kabul edileceğinden veriler etkilenmez.