為什么參數(shù)化SQL查詢可以防止SQL注入?
網(wǎng)友解答: sql注入就是指我們在URL中傳遞變量testid,并且提供值為23,由于它是對數(shù)據(jù)庫進(jìn)行動(dòng)態(tài)查詢的請求(其中?testid=23表示數(shù)據(jù)庫查詢變量),所以我們可以在URL中
sql注入就是指我們在URL中傳遞變量testid,并且提供值為23,由于它是對數(shù)據(jù)庫進(jìn)行動(dòng)態(tài)查詢的請求(其中?testid=23表示數(shù)據(jù)庫查詢變量),所以我們可以在URL中嵌入惡意SQL語句。
首先我們定義一個(gè)存儲過程根據(jù)jobId來查找jobs表中的數(shù)據(jù)
接著修改我們的Web程序使用參數(shù)化的存儲過程進(jìn)行數(shù)據(jù)查詢。
現(xiàn)在我們通過參數(shù)化存儲過程進(jìn)行數(shù)據(jù)庫查詢,這里我們把之前添加的正則表達(dá)式校驗(yàn)注釋掉。大家看到當(dāng)我們試圖在URL中嵌入惡意的SQL語句時(shí),參數(shù)化存儲過程已經(jīng)幫我們校驗(yàn)出傳遞給數(shù)據(jù)庫的變量不是整形。
網(wǎng)友解答:1. 參數(shù)化預(yù)編譯之所以能防御住SQL注入,只要是基于以下2點(diǎn):
1) setString(): WEB程序接收字符串的場景
將用戶輸入的參數(shù)全部強(qiáng)制轉(zhuǎn)換為字符串,并進(jìn)行適當(dāng)?shù)霓D(zhuǎn)義,防止了閉合的產(chǎn)生
2) setInt(): WEB程序接收整型的場景
將用戶輸入的非整型參數(shù)強(qiáng)制轉(zhuǎn)換為整型,并去除潛在的"非整型注入字符",類似與PHP中的intVal()防御思路
2. 并不是說使用了參數(shù)化預(yù)編譯方法執(zhí)行SQL,就不會有注入的發(fā)生了,當(dāng)WEB系統(tǒng)和DataBase系統(tǒng)的字符集配置不當(dāng),
也可能會導(dǎo)致寬字節(jié)注入的發(fā)生
參數(shù)化查詢例子:
class DBExample
{
private static string connectionString = "Data Source=.;Initial Catalog=Test;Integrated Security=True";
static void Main(string[] args)
{
MyLogin("b", "a");
MyLogin("b' or 1=1--", "a");
}
private static void MyLogin(string userName, string password)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Conn();
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
comm.CommandText = "select COUNT(*) from userinfo where Password = @Password and UserName = @UserName";
comm.Parameters.AddRange(
new SqlParameter[]{
new SqlParameter("@Password", SqlDbType.VarChar) { Value = password},
new SqlParameter("@UserName", SqlDbType.VarChar) { Value = userName},
});
comm.ExecuteNonQuery();
}
}
}
實(shí)際執(zhí)行的SQL:
exec sp_executesql N'select COUNT(*) from userinfo where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(1)',@Password='a',@UserName='b'
exec sp_executesql N'select COUNT(*) from userinfo where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(11)',@Password='a',@UserName='b'' or 1=1—'