SQL 注入示例

假設對 Web 應用程式的登入處理程式的呼叫如下所示:

https://somepage.com/ajax/login.ashx?username=admin&password=123

現在在 login.ashx 中,你可以閱讀以下值:

strUserName = getHttpsRequestParameterString("username");
strPassword = getHttpsRequestParameterString("password");

並查詢你的資料庫以確定是否存在具有該密碼的使用者。

因此,你構造一個 SQL 查詢字串:

txtSQL = "SELECT * FROM Users WHERE username = '" + strUserName + "' AND password = '"+ strPassword +"'";

如果使用者名稱和密碼不包含引號,這將起作用。

但是,如果其中一個引數確實包含引號,則傳送到資料庫的 SQL 將如下所示:

-- strUserName = "d'Alambert";
txtSQL = "SELECT * FROM Users WHERE username = 'd'Alambert' AND password = '123'";

這將導致語法錯誤,因為 d'Alambertd 之後的引用結束了 SQL 字串。

你可以通過轉義使用者名稱和密碼中的引號來更正此問題,例如:

strUserName = strUserName.Replace("'", "''");
strPassword = strPassword.Replace("'", "''");

但是,使用引數更合適:

cmd.CommandText = "SELECT * FROM Users WHERE username = @username AND password = @password";

cmd.Parameters.Add("@username", strUserName);
cmd.Parameters.Add("@password", strPassword);

如果你不使用引數,並且忘記在其中一個值中替換引號,那麼惡意使用者(也稱為黑客)可以使用它來在你的資料庫上執行 SQL 命令。

例如,如果攻擊者是邪惡的,他/她將設定密碼

lol'; DROP DATABASE master; -- 

然後 SQL 將如下所示:

"SELECT * FROM Users WHERE username = 'somebody' AND password = 'lol'; DROP DATABASE master; --'";

不幸的是,這是有效的 SQL,DB 將執行此操作!

這種型別的漏洞被稱為 SQL 注入。

惡意使用者可以執行許多其他操作,例如竊取每個使用者的電子郵件地址,竊取每個人的密碼,竊取信用卡號,竊取資料庫中的任何資料量等。

這就是為什麼你總是需要轉義你的字串。
事實上你遲早會忘記這樣做,這正是你應該使用引數的原因。因為如果你使用引數,那麼你的程式語言框架將為你做任何必要的轉義。