最好習慣用SqlParameter
iThome電腦報498期(2011..04.09)有著一則這樣的新聞Mass SQL Injection來襲,百萬網址受駭
SQL Injection這個名詞我想大慨不用多作解釋,而它不是個新名詞了,只是這麼多年來它始終存
在於我們的Web Application中,就像小強存在我們的生活中一樣
這則新聞中提到被駭的網站中,以ASP及ASP.NET網站數量最多,但真的用ASP及ASP.NET這麼
脆弱嗎?這倒也不是,而是寫code的我們該負起一些責任,常在論壇中看到以下類似的程式碼
select * from xx where code ='"+Request.QueryString["code"]+"'
這樣的程式碼,雖然不至於會錯,但它是卻為SQL Injection開啟大門,就像聲聲呼喚SQL Injection
來你家坐坐一樣,對於來自Request端的字串完全無過濾,原封不動的傳入,幸好在ASP.NET裡提供
了一個東西叫做SqlParameter,或許有些人會反駁那就寫個function過濾一下就好了啊,幹麻用
SqlParameter呢,用SqlParameter還要多寫一堆程式碼,其實SqlParameter除了幫我們過濾不合法
的字元之外,它也做到了型態的過濾,長度的過濾等等動作,能夠提供我們的程式在執行SQL Command
時能更安全,而且其實它寫起來一點都不麻煩,重點還在於習慣它就好了
SqlParameter的用法大致如下 (一點都不麻煩)
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select * from basecode where code =@code";
command.Parameters.Add("@code", SqlDbType.VarChar, 4).Value = this.Code.Text;
.....
.....
}
conn.Close();
}
再來看前陣子遇到的另一個論壇例子(連結就不po了),原發問者的問題大致是遇到在下SQL Command時
,因為時間條件的字串含有『上午,下午』這樣的文字,以致於會傳回例外的錯誤,而原發問者本身的
程式碼也是用串字串的方式,當然解法可以針對時間條件的字串去拆解再組合之類的方法來處理,不過
這也太麻煩了,如果使用SqlParameter來進行SQL Command的處理,這個問題應該早就不會發生了
,接著就以這個例子示範一下
在畫面上我拉了二個Button,一個是以SqlParameter方式進行SQL Command,而另一個則是以串
字串方式來進行SQL Command,另外拉了一個GridView以證明SQL Command有被正確的執行,
並且得到預期的結果
在.cs裡,直接以一個變數來模擬外界傳入的時間條件(當然是含有『上午,下午』這樣的文字)
string initdate = "2005/10/25 下午 07:06:18.000";
而採用SqlParameter的Button1_Click事件程式碼,如下
try
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select * from basecode where initdate =@initdate";
command.Parameters.Add("@initdate", SqlDbType.DateTime).Value = DateTime.Parse(initdate);
IDataReader idr = command.ExecuteReader();
this.GridView1.DataSource = idr;
this.GridView1.DataBind();
idr.Dispose();
}
conn.Close();
}
}
catch (Exception ex)
{
this.TextBox1.Text = ex.ToString();
}
執行結果,未發生Exception,且順利得到預期結果
串字串的Button2_Click事件程式碼,如下
try
{
using (SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["DBconnStr"].ToString()))
{
conn.Open();
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandText = "select * from basecode where initdate ='" + initdate + "'";
IDataReader idr = command.ExecuteReader();
this.GridView1.DataSource = idr;
this.GridView1.DataBind();
idr.Dispose();
}
conn.Close();
}
}
catch (Exception ex)
{
this.TextBox1.Text = ex.ToString();
}
執行結果,發生Exception
結論,與其想盡辦法過濾特殊字串來避免SQL Injection,或是花盡心思來處理字串以確保SQL
Command可被正常執行,倒不如快點跟SqlParameter成為好朋友吧!
By No.18