Godaddy伺服器上關於ASP.NET網站建設一些經驗 – 防SQL注入攻擊(三)

來源:互聯網
上載者:User

作者: 闕榮文 ( 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;
    }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.