結構化查詢語言(SQL)是一種用來和數據庫交互的文本語言SQL語言多種多樣,大多的方言版本都共同寬松地遵循SQL-92標准(最新的ANSI標准[譯者注:目前最新的是SQL-99])。SQL運行的典型的操作是“查詢”,它是可以讓數據庫返回“查詢結果記錄集”的語句集合。SQL語句可以修改數據庫的結構(用數據定義語言"DDL")和操作數據庫裡的數據(用數據操作語言"DML")。我們在這裡著重討論Transact-SQL(交互式SQL),應用於SQL-Server的SQL一種方言(非標准SQL)。
如果攻擊者可以插一系列的SQL語句進入應用程序的數據查詢時,Sql注入攻擊就可能發生。
一個典型的SQL語句是這樣的:
select id, forename, surname from authors
這個查詢語句將會從'authors'表中返回'id','forename'和'surname'列的所有行。返回的結果集也可以加以特定條件'author'限制:
select id, forename, surname from authors where forename = 'john' and surname = 'smith'
注意這裡很重要的一點是'john'和'smith'是被單引號引住的,假設'forename'和'surname'字段是來自於用戶的輸入,攻擊者就可能通過輸入非法字符串來對這個查詢進行SQL注入:
Forename:jo'hn
Surname: smith
查詢語句就會變成:
select id, forename, surname from authors where forename = 'jo'hn' and surname = 'smith'
當數據庫試圖執行這個查詢,它會返回這樣的錯誤:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near 'hn'
這是因為插入的單引號破壞了原來單引號引住的數據,數據庫執行到'hn'時失敗。如果攻擊者這樣輸入:
Forename: jo'; drop table authors--
Surname:
...authors表就會被刪掉,原因過一會再解釋。
似乎通過刪除用戶輸入的字符串中的單引號或者通過一些方法避免它們出現可以解決這個問題。誠然如此,但是要實施這個解決方法還有很多的困難。因為首先:不是所有的用戶提交的數據都是字符串形式,比如我們的用戶輸入通過'id'(看上去是個數字)來選擇一個用戶,我們的查詢可能會這樣:
select id,forename,surname from authors where id=1234
在這種情況下攻擊者可以輕易的在數值輸入後面添加SQL語句。在其他SQL方言中,使用著各種分隔符,比如MS Jet DBMS引擎,日期可以用'#'符號來分隔。
其次,避免單引號並不像開始我們想象的那樣是必要的解決辦法,原因下面討論。