使用LINQ解除SQL注入安全問題

作者: ξ簫音ξ  來源: 博客園  發布時間: 2008-09-26 10:57  閱讀: 13931 次  推薦: 0   原文鏈接   [收藏]  
 
[1] 使用LINQ解除SQL注入安全問題
[2] 使用LINQ解除SQL注入安全問題

在開發人員承受越來越多的安全責任之時,許多開發人員了解到的第一個Web應用安全漏洞,是一個被稱為“SQL注入”的極危險的命令注入形式。命令注入的原始的形式本是指這樣一種漏洞:攻擊者通過提供一個正常使用者意料之外的輸入,改變你的Web應用程序的運行方式,從而允許攻擊者運行服務器上的非授權的命令。無疑,SQL注入式攻擊是很常見的、被廣泛使用的攻擊形式。幸運的是,一旦我們理解了這個問題,就可以很容易地防止SQL注入式攻擊。更妙的是,現在微軟的數據訪問技術向.net開發人員提供了徹底地清除SQL注入漏洞的機會,當然前提是能夠正確使用。這種技術稱為“語言級集成查詢”(Language Integrated Query (LINQ)),并隨Visual Studio "Orcas" 和 .NET Framework 3.5一起發布。本文將討論如何通過LINQ強化Web應用程序的數據訪問代碼,從而解決通過SQL注入進行攻擊的問題。

SQL注入是一種Web應用程序的安全漏洞,通過它攻擊者可以將惡意數據提交給應用程序,欺騙應用程序在服務器上執行惡意的SQL命令。理論上講,這種攻擊是容易預防的,不過由于其允許攻擊者直接運行針對用戶關鍵數據的數據庫命令,從而成為一種常見的、危害性大的攻擊形式。在非常極端的情況下,攻擊者不但能夠自由地控制用戶的數據,還可以刪除數據表和數據庫,甚至控制整個數據庫服務器。

如果這種攻擊容易預防,那么為什么還如此危險呢?首先,由于眾所周知的經濟上的原因,你的應用數據庫是非常誘人的,可以引起攻擊者的極大注意。如果SQL注入漏洞在Web應用程序中可能存在著,那么對于一個攻擊者來說是很容易檢測到的,然后就可以利用它。很顯然,即使SQL注入錯誤并不是開發人員最經常犯的錯誤,它們也很容易被發現和利用。

 

對SQL注入的剖析

這里我們給出一個SQL注入的例子來說明兩個問題,一是SQL注入這種錯誤是很容易犯的,二是只要進行嚴格的程序設計,這種錯誤是很容易預防的。

這個示例用的Web應用程序包含一個名為SQLInjection.aspx簡單的客戶搜索頁面,這個頁面易于受到SQL注入攻擊。此頁面包含一個CompanyName的輸入服務器控件,還有一個數據表格控件,用于顯示從微軟的示例數據庫Northwind的搜索結果(這個數據庫可從SQL Server 2005中找到)。在搜索期間執行的這個查詢包含一個應用程序設計中很普通的錯誤:它動態地從用戶提供的輸入中生成查詢。這是Web應用程序數據訪問中的一個主要的錯誤,因為這樣實際上潛在地相信了用戶輸入,并直接將其發送給你的服務器。在從“搜索”的單擊事件啟動時,這個查詢看起來是這個樣子:

 

protected void btnSearch_Click(object sender, EventArgs e)
            {      String cmd = "SELECT [CustomerID], [CompanyName], [ContactName]
            FROM [Customers] WHERE CompanyName ='" + txtCompanyName.Text
            + "'";
            SqlDataSource1.SelectCommand = cmd;
            GridView1.Visible = true;
            }

在這種情況下,如果一個用戶輸入“Ernst Handel”作為公司名,并單擊“搜索”按鈕,作為響應屏幕會向用戶顯示那個公司的記錄,這正是我們所期望的理想情況。不過一個攻擊者可以輕易地操縱這個動態查詢。例如,攻擊者通過插入一個UNION子句,并用一個注釋符號終止這個語句的剩余部分。換句話說,攻擊者不是輸入“Ernst Handel”,而是輸入如下的內容:

 

Ernst Handel' UNION SELECT CustomerID, ShipName, ShipAddress
            FROM ORDERS--

其結果是這個SQL語句在服務器端執行,由于添加了這個惡意的請求。它會將這個動態的SQL查詢轉換為下面的樣子:

 

SELECT [CustomerID], [CompanyName],
            [ContactName]
            FROM [Customers]
            WHERE CompanyName ='Ernst Handel'
            UNION SELECT CustomerID, ShipName,
            ShipAddress
            FROM ORDERS--'

這是一個相當合法的SQL語句,它可以在應用程序數據庫上執行,返回order表中所有的客戶,這些客戶通過應用程序已經處理了定單。

典型的SQL防護

可以看出,在你的應用程序中創造并利用一個SQL注入漏洞是多么容易。幸運的是,如前所述,只需要采取幾項簡單的對策通常就可以預防SQL注入攻擊。最常用的、成本效率最高的預防SQL注入攻擊的方法是驗證應用程序中所有的最終用于數據訪問的數據輸入。用戶發出的任何輸入,不管是通過Web應用程序輸入的或者是常駐于數據存儲設備的,都要在服務器處理你的數據訪問命令之前在服務器端驗證其類型、長度、格式和范圍。不幸的是,基于代碼的對策并不十分安全,而且有可能失敗,特別是當發生如下情況時:

驗證程序設計不當

驗證僅在客戶層面執行

在應用程序中,驗證時遺漏了字段(有時即使是一個字段)。

防止SQL注入的另外一層涉及正確地確定應用程序中所有SQL查詢的參數,不管是在動態SQL語句中還是在存儲過程中。例如,如果代碼像下面這樣構建查詢,就比較安全:

 

SELECT [CustomerID], [CompanyName], [ContactName]
            FROM [Customers]
            WHERE CompanyName = @CompanyName

當作為SQL語句的一部分執行時,參數化查詢將輸入作為一個字面值,因此服務器就可能將帶參數的輸入作為可執行代碼。即使你使用了存儲過程,你仍然必須采取另外一步來確定輸入的參數,因為存儲過程并不對嵌入式查詢中的SQL注入提供保護。

即使采取這上述的簡單修正措施,SQL注入對許多公司來說仍然是一個大問題。對開發團隊的挑戰是要教育每一個開發人員謹慎對待這些類型的漏洞,采取有目的的和有效的安全標準來防止攻擊,增強標準和操作安全的評估, 確認無任何疏漏。這樣就會需要引入許多變量去保證應用程序安全,因此如果你選擇一項能夠使SQL注入式攻擊成為不可能的數據訪問技術,你的效率將會更高。這正是LINQ發揮作用之所在

[第1頁][第2頁]
0
0
 
標簽:Linq sql 注入
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()