從網上搜索的資料,結合自己的理解整理了一下,網友們在查看時若有發現問題,還請不吝指正,謝謝!
1、什么是SQL注入?
——官方說法:把SQL命令插入到web表單驗證的輸入框中,提交到服務器,以達到越過數據驗證的目的。
——通俗說法:在瀏覽器的某個網頁中,在身份驗證框或者數據查詢框中,通過輸入sql命令,影響SQL語句字符串的拼接,從而使原本執行不通過的SQL語句可以執行通過。
2、如何進行SQL注入?
——拼接SQL字符串:
比如在網站的登錄頁面中,在用戶名輸入框中輸入“or 1=1 --”,密碼輸入框中不輸入,然后點擊“登錄”按鈕,對於一些安全防護做的不太好的網站,可能就直接登進去了,應該叫做非法登錄了。舉例如下:
后台進行登錄驗證的代碼如下:(網上截的圖,主要看SQL字符串的拼接那塊。)
驗證用戶登錄的sql 如下:
select COUNT(*) from Users where Password = 'a' and UserName = 'b'
這段代碼返回Password 和UserName都匹配的用戶數量,如果大於1的話,那么就代表用戶存在。
SQL注入:我們在用戶名UserName輸入框中,輸入“b' or 1=1 --”(注意:“--”是SQL SERVER中的注釋,其他數據庫注釋標識可能不同),
然后原來的SQL語句就變成了:select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1 --',
實際執行的SQL語句是:select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1,因為后面的注釋了。
這樣這個SQL語句就變成了恆成立的,所以只要Users表中有數據,執行結果就是大於等於1的。
這樣SQL注入就成功了。
3、如何防止SQL注入?
————參數化查詢。
具體方法:
后台代碼如下:
這里我的理解是,通過參數化,把用戶的輸入信息中的單引號進行了轉義,從而使每一個輸入信息都作為一個單獨的字符串,比如像上面的“b' or 1=1 --”經過參數化處理后,就變成了“b'' or 1=1 --”,那么就不會改變原來SQL語句的語義了。
可以看到參數化查詢主要做了這些事情:
1:參數過濾,可以看到 @UserName='b'' or 1=1—'
2:執行計划重用
因為執行計划被重用,所以可以防止SQL注入。
最后,分析SQL注入的本質:
用戶寫了一段SQL 用來表示查找密碼是a的,用戶名是b的所有用戶的數量。
通過注入SQL,這段SQL現在表示的含義是查找(密碼是a的,並且用戶名是b的,) 或者1=1 的所有用戶的數量。
可以看到SQL的語意發生了改變,為什么發生了改變呢?,因為沒有重用以前的執行計划,因為對注入后的SQL語句重新進行了編譯,因為重新執行了語法解析。所以要保證SQL語義不變,即我想要表達SQL就是我想表達的意思,不是別的注入后的意思,就應該重用執行計划。
如果不能夠重用執行計划,那么就有SQL注入的風險,因為SQL的語意有可能會變化,所表達的查詢就可能變化。
任何動態的執行SQL 都有注入的風險,因為動態意味着不重用執行計划,而如果不重用執行計划的話,那么就基本上無法保證你寫的SQL所表示的意思就是你要表達的意思。
這就好像小時候的填空題,查找密碼是(____) 並且用戶名是(____)的用戶。
不管你填的是什么值,我所表達的就是這個意思。
最后再總結一句:因為參數化查詢可以重用執行計划,並且如果重用執行計划的話,SQL所要表達的語義就不會變化,所以就可以防止SQL注入,如果不能重用執行計划,就有可能出現SQL注入,
存儲過程也是一樣的道理,因為可以重用執行計划。
另外,對於上面說的“重用執行計划”這個詞不太明白,准備在下一次繼續學習整理一下。