|
前言:
SQL Injection(資料隱碼)攻擊,是個常見的網站入侵方法;某種程度上而言,造成這種攻擊生效的漏洞,是coder自己造成的,因為在操作資料庫的SQL語法中使用了"拼湊"的方式來組成所需的SQL語法,因而造成的嚴重漏洞;防堵的方法有很多,像是過濾查詢語句、限縮查詢資料庫帳號的使用權限、使用參數(Paramater)方式進行資料庫操作..等,本文將簡介如何使用ADODB.Command物件搭配Paramater來進行操作資料庫的動作。
使用環境:IIS + ASP 3.0
資料庫:可搭配SQL Server或Access
本文:
首先介紹如何將原本的SQL 語句變更為使用ADODB.Command物件並配合使用參數來執行
原本的執行方法原始碼如下:-
- set conn=server.createobject("ADODB.Connection"):conn.open "driver={sql server};database=school;server=127.0.0.1; uid=username;pwd=12345678"
- set rs=Server.CreateObject("ADODB.Recordset")
- sql="select * from TableName where TID = '"& TID &"' order by StartDate"
- rs.open sql,conn,3,3
複製代碼 變換說明:
第一行set conn保持原樣,第二行可以完全刪除,第三行sql語句的部分,應改為如下的語句- sql="select * from TableName where TID = ? order by StartDate"
複製代碼 變更的重點在於,把原本拼湊成的參數,變換成?(半型問號),其餘保持不變,接下來就是加入Adodb.Command物件來執行SQL語句:- Set cmd = Server.CreateObject("ADODB.Command")
- With cmd
- .ActiveConnection= conn
- .CommandType=1
- .NamedParameters=True
- .CommandText=sql
- .Parameters.Append .CreateParameter("@TID",2,1,,TID)
- end with
- set rs=cmd.execute
- cmd.cancel
- set cmd = nothing
複製代碼 其中注意到 .Parameters.Append 這一行的.CreateParameter("@TID",2,1,,TID)
@TID為參數名稱,2表示這個參數使用的DataType是SmallInt(2-Byte),1表示這是個input的參數
第四個空白欄位是用來表示這個參數輸入資料的大小,一般用於DataType為字元類別時使用
最後一個TID就是要輸入的資料,可以是變數,也可以是實際資料
由於這是一個查詢語句,因此我們需要把執行結果丟入一個Adodb.recordset物件,以便之後使用
因此加入了set rs=cmd.execute 這樣的語句,之後就可以用rs("FieldName")這樣的方式,來讀取資料表的內容
接下來兩句,是物件使用後就宣告消滅的一個使用習慣
以下為變更後,完整的程式碼- set conn=server.createobject("ADODB.Connection"):conn.open "driver={sql server};database=school;server=127.0.0.1; uid=username;pwd=testpassword"
- Set cmd = Server.CreateObject("ADODB.Command")
- With cmd
- .ActiveConnection= conn
- .CommandType=1
- .NamedParameters=True
- .CommandText=sql
- .Parameters.Append .CreateParameter("@TID",2,1,,TID)
- end with
- set rs=cmd.execute
- cmd.cancel
- set cmd = nothing
複製代碼 以上為SQL語句為Select的使用方法,當使用Update、Insert、Delete做為執行命令時,又有另外一種執行方法
以下將介紹使用Update語法時,使用的方法,底下是完整的語句-
- set conn=server.createobject("ADODB.Connection"):conn.open "driver={sql server};database=school;server=127.0.0.1; uid=username;pwd=testpassword"
- sqlstr = "UPDATE TableName "
- sqlstr = sqlstr & " SET ItemNumber = ?,MemberType=?,MemberName=? "
- sqlstr = sqlstr & " ,MemberJobList = ?,Other =? "
- sqlstr = sqlstr & " WHERE ReportTableID=? AND MemberTableID=? "
- Set cmd = Server.CreateObject("ADODB.Command")
- With cmd
- .ActiveConnection= conn
- .CommandType=1
- .NamedParameters=True
- .CommandText=sqlstr
- .Parameters.Append .CreateParameter("@ItemNumber",16,1,,ItemNumber)
- .Parameters.Append .CreateParameter("@MemberType",202,1,20,MemberType)
- .Parameters.Append .CreateParameter("@MemberName",202,1,50,MemberName)
- .Parameters.Append .CreateParameter("@MemberJobList",202,1,500,MemberJobList)
- .Parameters.Append .CreateParameter("@Other",202,1,500,Other)
- .Parameters.Append .CreateParameter("@ReportTableID",3,1,,ReportTableID)
- .Parameters.Append .CreateParameter("@MemberTableID",3,1,,MemberTableID)
- end with
- cmd.execute howmany
- cmd.cancel
- set cmd = nothing
- conn.close
複製代碼 程式碼說明:
在這個部分,sqlstr為SQL語句的組成,與使用SELECT語句時相同,把所有原本拼湊變數的地方,全數換成?(半型問號); .Parameters.Append 的部分也是一樣,要針對每個參數使用的內容做個別的設定,須注意參數的加入順序,必須與sqlstr語句中每一個問號相對應,順序錯誤將會造成執行上的問題。
接著特別注意到cmd.execute howmany這一句,cmd.execute 是執行SQL語句,後面加上howmany可以把執行結果傳回,使用者可以根據讀取howmany獲得一個數值,這個數值代表的是該次執行SQL語句後,有多少筆資料受到影響。
例如,我們使用的UPDATE語句只會更新一筆資料,那麼執行後,howmany的數值會變為1,如果是0,某種程度上代表著該次執行是失敗的(沒有達到預期的效果)。如此可以用來判斷執行的結果是否順利;當然,不加上howmany,一樣可以執行。至於這一行後面的,就不多敘述了。
另外關於SQL語句中?(半形問號)的使用,根據瞭解,像是「SET ItemNumber = ?」這樣的語句,可以換成「SET ItemNumber = @ItemNumber」這樣的型態,而在 『.Parameters.Append .CreateParameter("@ItemNumber",16,1,,ItemNumber)』這個部分,就可以透過紅字的地方,做為對應的根據,如此就不需要按照?(問號)的出現順序,做新增參數的動作。(PS:此段文字上未經使用證實)
以上為介紹在ASP下使用Command物件及Paramater查詢資料庫的方法;搭配Paramater使用可有效防止SQL Injection的攻擊,建議把有遭受SQL Injection攻擊疑慮的ASP程式碼,通通改成此一方式。
參考網頁:
[1] http://www.w3schools.com/ADO/ado_ref_parameter.asp
[2] SQL Injection (資料隱碼)– 駭客的 SQL填空遊戲(上) http://www.microsoft.com/taiwan/sql/SQL_Injection_G1.htm |
|