系統中安全性是非常重要的,為了保證安全性很多解決方案被應用到系統中,比如架設防火牆防止數據庫服務器直接暴露給外部訪問者、使用數據庫的授權機制防止未授權的用戶訪問數據庫,這些解決方案可以很大程度上避免了系統受攻擊,但是如果開發人員不注意SQL的安全性造成了SQL注入漏洞,那么所有的這些解決方案都形同虛設了,因為通過SQL注入漏洞,惡意訪問者可以堂而皇之的對數據庫進行任意操作,因為惡意訪問者破壞數據庫時所使用的一切操作都看起來是合法。我們來看一下什么是SQL注入漏洞。
到目前為止,本書演示的SQL語句都是靜態的SQL語句,比如下面的SQL用於校驗用戶名為“admin”的用戶的密碼是否是“123456”,如果密碼正確則PwdCorrect的值為true,否則為false:
SELECT (FPassword="123456") AS PwdCorrect FROM T_User WHERE FUser="admin" 在實際開發過程中一般是開發人員提供一個界面,允許用戶輸入用戶名和密碼,然后程序讀取用戶輸入用戶名和密碼來構造SQL 語句來校驗用戶名和密碼是否正確。實現的代碼如下: string user=txtUser.getText(); string password = txtPassword.getText(); rs = ExuecuteQuery("SELECT (FPassword=""+password+"") AS PwdCorrect FROM T_User WHERE FUser=""+password+"""); if(rs.getBool("PwdCorrect ")==true) { ShowMessage("密碼正確"); } else { ShowMessage("密碼錯誤"); }
這里采用拼接字符串的方式根據用戶錄入的用戶名和密碼來構建SQL語句,如果用戶名為“guest”,密碼為“123456”,那么拼接出來的SQL語句如下:
SELECT (FPassword="123456") AS PwdCorrect FROM T_User WHERE FUser="guest"
這看起來是沒有任何問題的,但是試想如果惡意攻擊者在用戶名輸入框中隨意輸入一個“abc”,而在密碼數據框中輸入“1" or "1"="1”,那么拼接出來的SQL語句如下:
SELECT (FPassword="1" or "1"="1") AS PwdCorrect FROM T_User WHERE FUser="abc"
由於“"1"="1"”這個表達式永遠返回true,而true與任何布爾值的or 運算的結果都是true,那么無論正確密碼是什么“FPassword="1" or "1"="1"”的計算值永遠是true,這樣惡意攻擊者就可以使用任何帳戶登錄系統了。十分驚訝吧!這樣的漏洞就被稱作“SQL注入漏洞(SQL
Injection)”。
對付SQL注入漏洞有兩種方式:過濾敏感字符和使用參數化SQL。