如何防止SQL注入攻擊
SQL注入攻擊的危害性很大,在講解其防止方法之前,資料庫管理員有必要想了解一下其攻擊的原理,這有利於管理員採取有針對性的防治措施。
一、SQL注入攻擊的簡單示例
statement:="select * from users where value="+a_variable+"
上面這條語句是很普通的一條sql語句,主要實現的功能就是讓使用者輸入一個員工編號然後查詢這個員工的資訊。但是若這條語句被不法攻擊者改裝過後,就可能成為破壞資料的黑手。如攻擊者在輸入變數的時候,輸入以下內容SA001';drop table c_order--。那麼以上這條SQL語句在執行的時候就變為了select * from users where values='SA001';drop table c_order--。
這條語句是什麼意思呢?'SA001'後面的分號表示一個查詢的結束和另一條語句的開始。c_order後面的雙連字元指示當前行餘下的部分只是一個註釋,應該忽略。如果修改後的程式碼語法正確,則伺服器將執行該程式碼。系統在處理這條語句時,將首先執行查詢語句,查到使用者編號為SA001的使用者資訊。然後,資料庫將刪除表c_order(如果沒有其他主鍵等相關約束,則刪除操作就會成功)。只要注入的SQL程式碼語法正確,便無法採用程式設計方式來檢驗篡改。因此,必須驗證所有使用者輸入,並仔細檢查在您所用的伺服器中執行構造SQL命令的程式碼。
二、SQL注入攻擊原理
SQL注入是目前比較常見的針對資料庫的一種攻擊方式。在這種攻擊方式中,攻擊者會將一些惡意程式碼插入到字串中。然後會通過各種手段將該字串傳遞到SQLServer資料庫的例項中進行分析和執行。只要這個惡意程式碼符合SQL語句的規則,則在程式碼編譯與執行的時候,就不會被系統發現。
SQL注入攻擊的主要形式有兩種。一是直接將程式碼插入到與SQL命令串聯在一起並使得其以執行的使用者輸入變數。上面筆者舉的例子就是採用了這種方法。由於其直接與SQL語句捆綁,故也被稱為直接注入式攻擊法。二是一種間接的攻擊方法,它將惡意程式碼注入要在表中儲存或者作為原資料儲存的字串。在儲存的字串中會連線到一個動態的SQL命令中,以執行一些惡意的SQL程式碼。
注入過程的工作方式的提前終止文字字串,然後追加一個新的命令。如以直接注入式攻擊為例。就是在使用者輸入變數的時候,先用一個分號結束當前的語句。然後再插入一個惡意SQL語句即可。由於插入的命令可能在執行前追加其他字串,因此攻擊者常常用註釋“--”來終止注入的字串。執行時,系統會認為此後語句位註釋,故後續的文字將被忽略,不被編譯和執行。
三、SQL注入攻擊的防治
1、普通使用者與系統管理員使用者的許可權要有嚴格的區分
如果一個普通使用者在使用查詢語句中嵌入另一個drop table語句,那麼是否允許執行呢?由於drop語句關係到資料庫的基本物件,故要操作這個語句使用者必須有相關的許可權。在許可權設計中,對於終端使用者,即應用軟體的使用者,沒有必要給他們資料庫物件的建立、刪除等許可權。那麼即使在他們使用SQL語句中帶有嵌入式的惡意程式碼,由於其使用者許可權的限制,這些程式碼也將無法被執行。故應用程式在設計的時候,最好把系統管理員使用者和普通使用者區分開來。如此可以最大限度的減少注入式攻擊對資料庫帶來的危害。
2、強迫使用引數化語句
如果在編寫SQL語句的時候,使用者輸入的變數不是直接嵌入到SQL語句,而是通過引數來傳遞這個變數的話,那麼就可以有效的防治SQL注入攻擊。也就是說,使用者的輸入絕對不能直接被嵌入待SQL語句中。與此相反,使用者的輸入的內容必須進行過濾,或者使用引數化的語句來傳遞使用者輸入的變數。引數化的內容必須進行過濾,或者使用引數化的語句來傳遞使用者輸入的變數。引數化的語句使用引數而不是將使用者輸入變數嵌入到SQL語句中。採用這種措施,可以杜絕大部分的SQL注入攻擊。不過可惜的是,現在支援引數化語句的資料庫引擎並不多。不過資料庫工程師在開發產品的時候要儘量採用引數化的語句。
3、加強對使用者輸入的驗證
總體來說,防治SQL注入攻擊可以採用兩種方法,一是加強對使用者輸入內容的檢查與驗證;二是強迫使用引數化語句來傳遞使用者輸入的內容。在SQLServer資料庫中,有比較多的使用者輸入內容驗證工具,可以幫助管理員來對付SQL注入攻擊。測試字串變數的內容,只接受所需的值。拒絕包含二進位制資料、轉義序列和註釋字元的輸入內容。這有助於防止指令碼注入,防止某些緩衝區溢位攻擊。測試使用者輸入內容的大小和資料型別,強制執行適當的限制與轉換。這即有助於防止友誼造成的緩衝區溢位,對於防治注入攻擊有比較明顯的效果。
可以使用儲存過程來驗證使用者的輸入。利用儲存過程可以實現對使用者輸入變數的過濾,如拒絕一些特殊的符號。如以上那個惡意程式碼中,只要儲存過程把那個分號過濾掉,那麼這個惡意程式碼也就沒有用武之地了。在執行SQL語句之前,可以通過資料庫的儲存過程,來拒絕接納一些特殊的符號。在不影響資料庫應用的前提下,應該讓資料庫拒絕包含以下字元的輸入。如分號分隔符,它是SQL注入攻擊的主要幫凶;如註釋分隔符,註釋只有在資料設計的時候時候用的到。一般使用者查詢語句中沒有必要註釋的內容,故可以直接把它拒絕掉,那麼即使在SQL語句中嵌入了惡意程式碼,他們也將毫無作為。
故始終通過測試型別、長度、格式和範圍來驗證使用者輸入,過濾使用者輸入的內容。這是防止SQL注入攻擊的常見並且行之有效的措施。