【摘要】本文對注入攻擊進行了深入研究使用鏈表實現了簡單Sql語句轉化為帶參數Sql有效防止了注入。
【關鍵詞】鏈表;注入;帶參數Sql語句
在操作數據庫的程序中我們一般都喜歡使用sql語句拼接的方式編寫程序,這樣編寫出的程序靈活性較高,不受制約,運行速度較快。但這樣的程序容易受到注入的為威脅,如你編寫一個sql語句來判斷用戶密碼是否存在:select top 1 * from User
where UserName=’admin’ and Pwd=’adminpwd’這條語句的兩個值Username和Pwd一般來自于用戶的輸入。正常用戶通常會填入用戶名和密碼,但別有用心的用戶會使用特殊的方法進行攻擊,比如他在用戶名里填寫一個admin’ or 1=1‘這樣sql語句就變成了select top 1 * from User where UserName=’admin’
or 1=1‘and Pwd=’adminpwd’注意這個or 1=1也就是不管用戶名密碼是不是成立where表達式的值總是成立的,這就是SQL注入攻擊的本質。
一、如何防范注入攻擊
我們知道注入攻擊的原理就可以進行防范,防范注入攻擊的方式大體分為2類:第一類是對用戶輸入的內容進行過濾,過濾掉用戶輸入’and or等這些特殊字符。這種方式比較簡單實現也相對容易。大部分網站都采用這種方式。代碼如下:
但是這種方式在參數特別多情況,會極大的降低效率,要確認哪個參數需要去判斷一遍,也給寫程序員帶來了很大的負擔,筆者就曾經遺漏了參數使網站被注入攻擊。另一類是利用帶參數的SQL語句,把需要的用戶輸入全部使用Sql參數代替,這樣在Sql語句執行時會把參數帶入執行,在執行完成時在把值填充入參數。如剛才的登陸Sql語句可以寫成:select top 1
* from User where UserName=@UserName and Pwd=@pwd .
@Username和@pwd為SQL語句的參數,以C#語言和Sqlserver數據庫為例代碼如下:
這種參數化的查詢優勢是安全性高,就算用戶使用注入攻擊對Sql語句進行截斷admin’or 1=1‘Sql語句也不會執行。同時使用Sql參數會提高Sql語句的執行速度。但是這種每次必須指定參數的做法使程序喪失了靈活性,對程序重用性是一種極大的挑戰,不得不在程序編寫時每次都使用Parameters。Add為Sql語句添加參數。綜合上面的兩種方式,我們可以發現帶參數的Sql語句比過濾用戶輸入內容的方式更加安全高效,但是程序員必須編寫更復雜的代碼。有沒有方法可以讓一般的Sql語句自動轉換為帶參數的Sql語句呢。在轉換之前我們必須先要研究格式化問題。
二、結論
為了能夠正確解析sql語句,必須使用一種數據結構,能夠非常方便的插入到這些關鍵字中,又不影響后面的關鍵字,這種結構只有鏈表,C#提供了鏈表結構。通過鏈表格式化可以把SQL語句分解成單個的關鍵字節點,經過作者實踐證明完全可以解釋簡單的Sql語句。