Godaddy服务器上关于ASP.NET网站建设一些经验 - 防SQL注入攻击(三)
作者: 闕榮文 ( querw )
什么是SQL注入攻擊,有什么危害
先來看一個例子說說SQL注入攻擊是怎么回事,有什么危害.
在有用戶參與的網站中,所有操作中最重要的就是登錄.要求用戶輸入用戶名和密碼,然后在數據庫里校驗輸入的有效性.
我相信很多人(反正我以前一直就是怎么寫的)寫類似下面的代碼:
(代碼1)
string strUserName = txtUserName.Text;
string strPwd = txtPwd.Text;
string strSql = "select * from UserTable where username = ";
strSql += "'" + strUserName "'";
strSql += " and password ='" + strPwd + "'";
...
像這樣依賴用戶輸入來"拼湊"SQL語句的代碼是極其脆弱的. 假設一個用戶(也許是黑客)輸入的密碼是 ' or '1'='1 用戶名無所謂什么字符,看看這條SQL語句會變成什么:
select * from UserTable where username = 'what ever you input' and password = '' or '1'='1'
執行這個語句會返回整個UserTable表,再加上很多網站的管理賬號的用戶名就是 admin, 那么悲劇的發生就無法避免了,入侵者很容易就以管理員的身份登錄了,不管你的密碼設置得多長,多復雜. 事實上入侵者能夠利用上述的漏洞獲取到遠遠比你想象的多的信息,如果他精通SQL的話,整個網站都有可能變成他的玩具. 所謂SQL注入攻擊,大概就是這個意思了.SQL注入攻擊使用正常的WEB瀏覽工具,防火墻對此無能為力,而且現成的攻擊工具很多,使用也簡單.如果網站存在這樣的漏洞的話,任何一個人都有可能輕松攻破你的網站.
如何防范?
在網上隨便搜一下,就可以得到 "通用防注入" 代碼,它的原理是檢查訪問者提交的(包括使用GET 和 POST方法)數據,如果內容里含有某些SQL敏感的單詞,則采取相應的防范措施. 比如某個"通用防注入"的關鍵字字典是: '|exec|insert|select|delete|update|count|chr|truncate|char|declare|--|script|*|char|set|(|) 所有提交的內容中含有上述任何一個單詞,都被認為是攻擊嘗試.
不可否認這是一個解決方案,但我認為這只是治標不治本,理由:
1. 打擊面過大,比如博客/新聞網站,用戶的提交包含上面的單詞是很正常的,但是如果過濾的話會被認為是入侵行為.
2. 沒有從根本上解決問題,黑客技術的發展非常快,所謂道高一尺,魔高一丈.這個關鍵字字典也許永遠都沒辦法包含所有危險的關鍵字.
解決問題要找根本,SQL注入漏洞的根源在于直接用訪問者的輸入 "拼湊" SQL語句并執行.那就不要拼湊SQL語句了 - 使用參數或者存儲過程. 通過參數或者存儲過程,SQL語句受開發者/管理員控制,用戶的輸入被限制在特定作用范圍,就好像被籠子關著的野獸,牙齒再尖利,也咬不到籠子外的東西.
(代碼2)
string strSql = "select * from UserTable where UserName = @UserName and Password = @Password";
SqlParameter[] param = new SqlParameter[]
{
????? new SqlParameter("@UserName", strName),
????? new SqlParameter("@Password", strPwd)
};
DataSet ds = db.OpenDataSetS(strSql, param);
...
現在,不管入侵者提交什么用戶名或者密碼,都被作為 @UserName 和 @Password 的值傳給數據庫引擎,而不在影響SQL語句本身.
另外提一句,適當做一些過濾總是有好處的. 比如這么一個鏈接 http://xxxx/userdetail.aspx?userid=100001
服務器頁面會用Request的QueryString方法(或者類似的方法,本文的寫作背景是ASP.NET / C# / SQL Server 2005)獲取userid的值,如果直接把userid作為SQL語句的一部分,那么就會造成一個SQL注入漏洞. 但是這里很明顯,userid是一個數值,如果使用前總是先把字符串轉成數值型,那么就可以避免攻擊.還有很多類似的地方,比如一般都有規定用戶名的最長字符數,再接到訪問者輸入時可以檢查一下. 總而言之,在邏輯上做一些檢測會使程序更加嚴謹,錯誤可控.
后記
筆者的網站就經歷過SQL注入攻擊,之前全部采用"拼湊"SQL語句的方式寫代碼,給了我一個慘痛的教訓.網站被安裝shell,重要郵箱被盜(郵箱密碼和網站admin密碼設置成一樣了,另一個慘痛教訓.)
域名被修改.(域名密碼和admin密碼也設置成一樣了,捶胸頓足...) 還好,最后"黑客"同志看在我們都是同胞弟兄的份上,把密碼都換給我了. 被狠狠的上了一課. 感謝他的好心,如果碰到一個有惡意的攻擊者...無法想象.
另外,我在網上搜索發現一種說法:使用參數并不能絕對杜絕SQL注入攻擊,不過也沒說出個所以然.我也不是很明白,如果您知道,能否告訴我一下(querw@sina.com)?非常感謝.
附錄: 代碼2中OpenDataSetS()函數
??? public System.Data.DataSet OpenDataSetS(string strSql, SqlParameter[] param)
??? {
??????? // 判斷連接字符串是否為空.
??????? if (!Open()) return null;
??????? DataSet ds = null;
??????? SqlDataAdapter da = new SqlDataAdapter();
??????? SqlCommand cmd = new SqlCommand();
??????? cmd.Connection = " *** my sql connection string ***";
??????? cmd.CommandType = CommandType.Text;
??????? cmd.CommandText = strSql;
????????? if (param != null)
????????? {
????????????? foreach (SqlParameter p in param)
????????????? {
????????????????? cmd.Parameters.Add(p);
????????????? }
????????? }
??????? da.SelectCommand = cmd;
??????? ds = new DataSet();
??????? da.Fill(ds);
??????? cmd.Dispose(); cmd = null;
??????? da.Dispose(); da = null;
??????? return ds;
??? }
總結
以上是生活随笔為你收集整理的Godaddy服务器上关于ASP.NET网站建设一些经验 - 防SQL注入攻击(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三角形 已知三点坐标求面积
- 下一篇: MSELoss() 函数