Saklı prosedürler sihirli bir şekilde SQL enjeksiyonunu engellemez, ancak çok daha kolay bir şekilde önlenmesini sağlar. Tek yapmanız gereken, aşağıdakine benzer bir şey (Postgres örneği):
CREATE OR REPLACE FUNCTION my_func (
IN in_user_id INT
)
[snip]
SELECT user_id, name, address FROM my_table WHERE user_id = in_user_id; --BAM! SQL INJECTION IMMUNE!!
[snip]
Bu kadar! Sorun yalnızca dize birleştirme (yani dinamik SQL) aracılığıyla bir sorgu oluştururken ortaya çıkar ve hatta bu durumlarda bile bağlayabilirsiniz! (Veritabanına göre değişir.)
Dinamik sorguda SQL enjeksiyonunu nasıl önleyebilirim:
Adım 1) Dinamik bir sorguya gerçekten ihtiyacınız olup olmadığını kendinize sorun. Yalnızca girişi ayarlamak için dizeleri birbirine yapıştırıyorsanız, muhtemelen yanlış yapıyorsunuz demektir. (Bu kuralın istisnaları vardır - bunun bir istisnası, bazı veritabanlarındaki sorguları bildirmektir, her yürütme için yeni bir sorgu derlemeye zorlamazsanız performans sorunlarınız olabilir. Ancak bu konuyu araştırmadan önce araştırın. )
Adım 2) RDBMS'niz için değişkeni ayarlamanın uygun yolunu araştırın. Örneğin Oracle şunları yapmanıza izin verir (dokümanlarından alıntı yaparak):
sql_stmt := 'UPDATE employees SET salary = salary + :1 WHERE '
|| v_column || ' = :2';
EXECUTE IMMEDIATE sql_stmt USING amount, column_value; --INJECTION IMMUNE!!
Burada hala girişi birleştirmiyorsunuz. Güvenle bağladınız! Yaşasın!
Veritabanınız yukarıdaki gibi bir şeyi desteklemiyorsa (umarım hiçbiri hala bu kadar kötü değildir, ancak şaşırmam) - ya da girişinizi gerçekten birleştirmek zorundaysanız ("bazen" durumundaki bildirimleri sorguladığınız gibi) Ben yukarıyı ima ettim), o zaman uygun bir kaçış işlevi kullanmalısınız. Kendin yazma. Örneğin postgres quote_literal () işlevini sağlar. Yani kaçardın:
sql_stmt := 'SELECT salary FROM employees WHERE name = ' || quote_literal(in_name);
Bu, eğer in_name '[snip] veya 1 = 1' ("veya 1 = 1" bölümü gibi) bir şey ise, kullanıcının tüm satırları seçerek kullanıcının yapmaması gereken maaşları görmesini sağlar!), Sonra quote_literal sizin poponuzu kaydeder sonuç dizesini yapmak:
SELECT salary FROM employees WHERE name = '[snip] or 1=1'
Hiçbir sonuç bulunmayacak (gerçekten garip isimleri olan bazı çalışanlarınız yoksa).
Bunun özü bu! Şimdi, sizi eve götürmek için SQL Injection konusunda Oracle guru Tom Kyte'nin klasik bir yazısına bağlantı vermeme izin verin : Linky