SQL注入解決思路(C#樣本),

來源:互聯網
上載者:User

SQL注入解決思路(C#樣本),

最近在編程中遇到一個SQL注入防護的問題。在這裡順便把SQL注入小結一下。以MYSQL(5.1)為例。

一、常規的SQL語句

觀察SQL語句

SELECT * FROM [tableName] WHERE col1='value1'

這個語句由3個部分組成,SELECT子句篩選得到結果,FROM子句指定了篩選的範圍,WHERE子句指定了條件。當在其中進行如下置換:
SELECT * FROM [tableName] WHERE 1
之後,選出了[tableName]表中的全部內容。分析其文法不難發現,WHERE將其後的真值運算式求值,然後作為篩選的條件。


二、WHERE子句的理解現在(在MYSQL5.1)中測試以下語句
SELECT * FROM [tableName] WHERE false or 1=‘1’ and '1'='1' and "1"="1"
同樣得到了[tableName]表種的全部內容。
這個測試說明了兩點:
1、WHERE對後面的運算式進行真值計算
2、不帶符號、'與"都可以通過真值測試,可能不是個別特殊符號的問題


三、WHERE子句在編程中的使用通常是採用字串拼接的方式來構建WHERE子句。一般有:
SELECT * + FROM [tableName] + WHERE col1=' + value1 + ' 
其中的value1常常是由輸入所得。然而當WHERE子句具備(二)中的某種特徵時就可能存在意外了。如果只是按照拼接來構建WHERE子句的話,那麼WHERE子句可能會演化成這樣的形式:
SELECT * FROM [tableName] WHERE col1='badvalue' or 1='1'
也就是說,使用者熟悉SQL語句並精心構造了一個包含SQL特殊字元的輸入{badvalue' or 1='1},這時候會返回整張表。
當程式員採用"工作時,類似也有:
SELECT * FROM [tableName] WHERE col1="badvalue" or 1="1"
中的{badvalue" or 1="1}。
總之,一旦程式員採用直接將使用者輸入拼接進SQL語句時就存在偷換WHERE真值的風險。像這樣,使用者通過簡單地改變終端輸入而改變了應用邏輯的情況,叫做注入。


四、更加奔放的情況觀察上面大括弧裡面的內容,在MYSQL(5.1)中還存在這樣的情況:
SELECT * FROM [tableName] WHERE col1='badvalue' ; select * from [another] where 1='1'
也就是說,填入{badvalue' ; select * from [another] where 1='1}。完全可以把填入括弧中的select換成drop、update等等。起作用的前提是程式員不作任何處理地將使用者輸入接入了SQL查詢語句中。
可以做一個簡單的結論,SQL特殊字元在概念上是嵌套的,然而由於在處理中使用了直接拼接的方式,使得使用者參與了SQL語句的編寫,輸入特殊字元讓SQL截短解析,最終導致意料以外的後果。


五、解決問題的現狀完全沒有必要搞得高深莫測。但是解決的方法通常是會引起爭論的。
我用的最久的語言是C#。因為某種二缺的原因,我第一門認真學習的語言是C#。在這裡給出一個C#的解決方案吧。


六、解決方案構思與部署主要是要隔離開使用者輸入對“構建”SQL語句的參與權。使用者輸入只能作為資料提供。只要滿足這個原則,WHERE子句的組裝還是比較清晰的。
我們可以盡量把非使用者輸入的部分寫完整,然後把使用者輸入的特殊字元全部轉義。這樣,就有了示意的Where函數

/**  * affirmNodePair 樣本:  *   {"or col1=","value1"}  *   {"and col2>","value2"}* * /public string Where (Dictionary<string,string> affirmNodePair){StringBuilder builder=new StringBuilder();// 預先處理builder.Append(" where 1 ");foreach (var item in affirmNodePair) {builder.Append(item.Key);builder.Append("'");//過濾使用者輸入:將使用者輸入的特殊字元轉義foreach (var c in item.Value) {switch (c) {case '\'':builder.Append(@"\");break;case '\"':builder.Append(@"\");break;case ';':builder.Append(@"\");break;default:break;}builder.Append(c);}builder.Append("'");builder.Append(" ");}return builder.ToString();}



這樣形成的Where子句類似於:
Where 1 or col1='value1' and col2>'value2'
當填入{badvalue' or 1=‘1}後得到轉義後的結果
Where 1 or col1='badvalue\' or 1=\'1'
在我測試使用的MYSQL(5.1)中能夠符合預期地報錯。具體的部署要結合實際情況,限於工作條件,這裡只提供了一個基礎性思路。謝謝大家耐心看完。

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.