發新話題
打印

[轉貼] 運用LINQ輕鬆清除SQL注入式攻擊

運用LINQ輕鬆清除SQL注入式攻擊

微軟的LINQ to SQL技術為.net開發人員提供了一種機會,使其可以清除所開發的Web應用程序中SQL注入式安全漏洞的可能性。 隨著對Web安全破壞的與日俱增,開發人員越來越深刻地認識到需要為其開發的應用程序的安全性承擔更大的責任,而且應用程序框架的廠商們也將更堅實的安全特性構建到其應用軟件中去。許多開發人員已經認識到構建安全應用程序和防止破壞性攻擊的最有效的方法就是從一開始就要安全地設計和實施應用程序。不幸的是,開發團隊往往缺乏訓練和資源來做出關於應用程序安全的科學設計決策。 在開發人員承受越來越多的安全責任之時,許多開發人員瞭解到的第一個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注入漏洞的一個簡單方法是在一次輸入中插入一個元字符(meta-character),一個應用程序會用這個字符生成一個數據庫訪問語句。例如,在任何包含一個搜索輸入欄的Web站點上,一個攻擊者可以輸入一個數據庫元字符,例如一個核對符號(),然後單擊「搜索」按鈕提交輸入。如果應用程序返回一個數據庫錯誤消息,攻擊者不但會知道他已經發現了一個應用程序的數據庫驅動部分,而且他還能注入更加有意義的命令,讓你的服務器執行它們。應用程序安全研究員Michael Sutton近來強調,發現那些易於受到SQL攻擊的站點是很容易的。他說,使用Google搜索API這種方法只需幾分鐘就可以確定大量的潛在的易受攻擊的站點。 對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」作為公司名,並單擊「搜索」按鈕,作為響應屏幕會向用戶顯示那個公司的記錄,這正是我們所期望的理想情況。不過一個攻擊者可以輕易地操縱這個動態查詢。例如,攻擊者通過插入一個...子句,並用一個註釋符號終止這個語句的剩餘部分。換句話說,攻擊者不是輸入「Ernst Handel」,而是輸入如下的內容:
Ernst Handel' ... SELECT CustomerID, ShipName, ShipAddress    FROM ORDERS--
其結果是這個SQL語句在服務器端執行,由於添加了這個惡意的請求。它會將這個動態的SQL查詢轉換為下面的樣子:
SELECT [CustomerID], [CompanyName],     [ContactName]   FROM [Customers]    WHERE CompanyName ='Ernst Handel'    ... SELECT CustomerID, ShipName,    ShipAddress    FROM ORDERS--'
這是一個相當合法的SQL語句,它可以在應用程序數據庫上執行,返回order表中所有的客戶,這些客戶通過應用程序已經處理了定單。


保障LINQ數據庫存取的安全 LINQ to SQL在專用於數據存取時,清除了SQL注入存在於你的應用程序中的可能性,原因很簡單:LINQ代表你執行的每次查詢都加上了具體的參數。在LINQ從你植入的查詢語句中構建SQL查詢時,無論源自何處,提交給查詢的任何輸入都被當作字面值。而且,通過IntelliSense和編譯時的語法檢查,LINQ與Visual Studio Orcas的集成可以幫助開發人員構建合法的查詢。編譯器可以捕捉大量的對查詢的錯誤使用,這些錯誤使用可以將功能上的缺陷或其它類型的漏洞帶入到你的應用程序中。與此不同的是,在你獲知它正確與否之前,你編寫的SQL語句只在運行時刻在數據庫系統上解析。針對LINQ to SQL的唯一攻擊途徑是攻擊者欺騙LINQ形成非法的或無意識的SQL。幸運的是,語言和編譯器就是設計來保護這個方面的。 在清楚了上述的基本思想後,下面我們就展示應該如何運用LINQ to SQL防護SQL注入式攻擊,並具體討論一個客戶搜索的例子。第一步是創建數據庫中有關數據的對象模型。Visual Studio Orcas包含一個新的對象關係設計器(Object Relational Designer),這個設計器使你能夠生成一個完全的對象模型。為了為我們的Northwind Customers表構建一個對像模型,你通過選擇「增加新項目…」並選擇「LINQ to SQL File」模板(這個模板是在對像關係設計器中打開的),在應用程序中創建一個LINQ to SQL的數據庫。為了給 Customers表自動構建完全的對象模型,在服務器資源管理器 (Server Explorer)中選擇這個表,並將它拖到對像關係設計器的設計層面上。在這個例子中,對像關係設計器增加了一個名為Customers.designer.cs的文件,這個文件以代碼的形式定義了你將要使用的類,而不是編寫代碼直接與數據庫進行交互。 在為Customers表中的數據定義了對象模型的類之後中,你可以為客戶的數據搜索頁面直接以代碼的形式查詢數據。LINQ-powered 頁面(LINQtoSQL.aspx.cs)的Page_Load方法,具體展現了由對像關係設計器創建的CustomersDataContext類,重新使用了前面在SQLInjection.aspx頁面中使用的連接字符串。下面的LINQ查詢重新使用了與where子句匹配的Customer對象的集合。
protected void Page_Load(object sender, EventArgs e)   {      string connectionString =         ConfigurationManager.ConnectionStrings         ["northwndConnectionString1"].ConnectionString;         CustomersDataContext db = new         CustomersDataContext(connectionString);         GridView1.DataSource =           from customer in db.Customers          where customer.CompanyName ==           txtCompanyName.Text          orderby customer.CompanyName          select customer;         GridView1.DataBind();   }
在使用了LINQ to SQL之後,如果我們將「Ernst Handel」作為搜索值,由LINQ在運行時生成並在服務器上執行的SQL語句看起來將會是如下這個樣子:
SELECT [t0].[CustomerID], [t0].[CompanyName],      [t0].[ContactName], [t0].[ContactTitle], [t0].[Address],      [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country],      [t0].[Phone], [t0].[Fax]   FROM [dbo].[Customers] AS [t0]   WHERE [t0].[CompanyName] = @p0   ORDER BY [t0].[CompanyName]}
可以看出,WHERE子句自動被加上了參數,因此,用傳統的SQL注入式攻擊是無法造成破壞的。不管用戶將什麼值作為輸入提交給搜索頁面,這個查詢是安全的,它不允許用戶的輸入執行服務器上的命令。如果你輸入了前面例子中用來實施SQL注入攻擊的字符串,查詢並不會返回任何信息。事實上,一個用戶用這個查詢可以進行的最大的破壞是執行一次強力攻擊(或稱蠻力攻擊(Brute force attack)),主要通過使用搜索功能窮舉Customers表中所有公司的記錄,其使用的方法是猜測每一個可能的值。不過,即使這樣也只提供了那個頁面上所暴露的Customers表中的值,並不會給攻擊者注入命令的機會,這裡的命令指的是訪問數據庫中額外的數據表的命令。 LINQ與安全 正如前面的例子所顯示的那樣,在Web應用程序中引入SQL注入漏洞是很容易的,不過採用適當的方法也容易修正這些漏洞。但是,沒有什麼方法天生就能防止開發人員犯這些簡單的但卻是危險的錯誤。然而,微軟的LINQ to SQL技術通過讓開發人員直接與對像模型交互而不是直接與數據庫交互,消除了來自數據庫應用程序的SQL注入攻擊的可能性。內建於c#和Visual Basic的 LINQ基礎結構關注正確地表述合法而安全的SQL語句,可以防止SQL注入攻擊,並使開發人員專注於對他們來說最自然的程序設計語言。不管你是將LINQ to SQL用作新的.NET應用程序開發的一部分,還是對它進行花樣翻新,用於現有的實際應用程序的數據訪問,你都是作了一個構建更安全的應用程序的選擇。


[ 本帖最後由 yumr 於 2007-12-28 18:39 編輯 ]

TOP

發新話題