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'Alambert
中 d
之後的引用結束了 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 注入。
惡意使用者可以執行許多其他操作,例如竊取每個使用者的電子郵件地址,竊取每個人的密碼,竊取信用卡號,竊取資料庫中的任何資料量等。
這就是為什麼你總是需要轉義你的字串。
事實上你遲早會忘記這樣做,這正是你應該使用引數的原因。因為如果你使用引數,那麼你的程式語言框架將為你做任何必要的轉義。