ASP.NET腳本過濾-防止跨站腳本攻擊

 

沒辦法,有時候程序員做事需要非程序員去提醒,去找解決辦法,我只能這樣了

ASP.Net 1.1後引入了對提交表單自動檢查是否存在XSS(跨站腳本攻擊)的能力。當用戶試圖用<xxxx>之類的輸入影響頁面返回結果的時候,ASP.Net的引擎會引發一個 HttpRequestValidationExceptioin。默認情況下會返回如下文字的頁面:

Server Error in '/YourApplicationPath' Application

A potentially dangerous Request.Form value was detected from the client
(txtName="<b>").


Description: Request Validation has detected a potentially dangerous client input value, and processing of the request has been aborted. This value may indicate an attempt to compromise the security of your application, such as a cross-site scripting attack. You can disable request validation by setting validateRequest=false in the Page directive or in the configuration section. However, it is strongly recommended that your application explicitly check all inputs in this case.

Exception Details: System.Web.HttpRequestValidationException: A potentially dangerous Request.Form value was detected from the client (txtName="<b>").

....


這是ASP.Net提供的一個很重要的安全特性。因爲很多程序員對安全沒有概念,甚至都不知道XSS這種攻擊的存在,知道主動去防護的就更少了。ASP.Net在這一點上做到默認安全。這樣讓對安全不是很瞭解的程序員依舊可以寫出有一定安全防護能力的網站。

但是,當我Google搜索 HttpRequestValidationException 或者 "A potentially dangerous Request.Form value was detected from the client"的時候,驚奇的發現大部分人給出的解決方案竟然是在ASP.Net頁面描述中通過設置 validateRequest=false 來禁用這個特性,而不去關心那個程序員的網站是否真的不需要這個特性。看得我這叫一個膽戰心驚。安全意識應該時時刻刻在每一個程序員的心裏,不管你對安全的概念瞭解多少,一個主動的意識在腦子裏,你的站點就會安全很多。

爲什麼很多程序員想要禁止 validateRequest 呢?有一部分是真的需要用戶輸入"<>"之類的字符。這就不必說了。還有一部分其實並不是用戶允許輸入那些容易引起XSS的字符,而是討厭這種報錯的形式,畢竟一大段英文加上一個ASP.Net典型異常錯誤信息,顯得這個站點出錯了,而不是用戶輸入了非法的字符,可是自己又不知道怎麼不讓它報錯,自己來處理報錯。

對於希望很好的處理這個錯誤信息,而不使用默認ASP.Net異常報錯信息的程序員們,你們不要禁用validateRequest=false。

正確的做法是在你當前頁面添加Page_Error()函數,來捕獲所有頁面處理過程中發生的而沒有處理的異常。然後給用戶一個合法的報錯信息。如果當前頁面沒有Page_Error(),這個異常將會送到Global.asax的Application_Error()來處理,你也可以在那裏寫通用的異常報錯處理函數。如果兩個地方都沒有寫異常處理函數,纔會顯示這個默認的報錯頁面呢。

舉例而言,處理這個異常其實只需要很簡短的一小段代碼就夠了。在頁面的Code-behind頁面中加入這麼一段代碼:

protected void Page_Error( object sender, EventArgs e)
... {
     Exception ex
= Server.GetLastError();
    
if (ex is HttpRequestValidationException)
    
... {
         Response.Write(
" 請您輸入合法字符串。 " );
         Server.ClearError();
// 如果不ClearError()這個異常會繼續傳到Application_Error()。
     }

}



這樣這個程序就可以截獲 HttpRequestValidationException 異常,而且可以按照程序員的意願返回一個合理的報錯信息。

這段代碼很簡單,所以我希望所有不是真的要允許用戶輸入<xxx>之類字符的朋友,千萬不要隨意的禁止這個安全特性,如果只是需要異常處理,那麼請用類似於上面的代碼來處理即可。

而對於那些通過 明確禁止了這個特性的程序員,自己一定要明白自己在做什麼,而且一定要自己手動的檢查必須過濾的字符串,否則你的站點很容易引發跨站腳本攻擊。

關於存在Rich Text Editor的頁面應該如何處理?

如果頁面有富文本編輯器的控件的,那麼必然會導致有<xxx>類的HTML標籤提交回來。在這種情況下,我們不得不將validateRequest="false"。那麼安全性怎麼處理?如何在這種情況下最大限度的預防跨站腳本攻擊呢?

根據微軟的建議,我們應該採取安全上稱爲“默認禁止,顯式允許”的策略。

首先,我們將輸入字符串用 HttpUtility.HtmlEncode()來編碼,將其中的HTML標籤徹底禁止。

然後,我們再對我們所感興趣的、並且是安全標籤,通過Replace()進行替換。比如,我們希望有"<b>"標籤,那麼我們就將"&lt;b&gt;"顯式的替換回"<b>"。

示例代碼如下:

   void submitBtn_Click( object sender, EventArgs e)
  
... {
    
// 將輸入字符串編碼,這樣所有的HTML標籤都失效了。
     StringBuilder sb = new StringBuilder(
                            HttpUtility.HtmlEncode(htmlInputTxt.Text));
    
// 然後我們選擇性的允許<b> 和 <i>
    sb.Replace( "&lt;b&gt;", "<b>");
     sb.Replace("&lt;/b&gt;", "");
     sb.Replace("&lt;i&gt;", "<i>");
     sb.Replace("&lt;/i&gt;", ""
);
     Response.Write(sb.ToString());
   }


這樣我們即允許了部分HTML標籤,又禁止了危險的標籤。

根據微軟提供的建議,我們要慎重允許下列HTML標籤,因爲這些HTML標籤都是有可能導致跨站腳本攻擊的。

  • <applet>
  • <body>
  • <embed>
  • <frame>
  • <script>
  • <frameset>
  • <html>
  • <iframe>
  • <img>
  • <style>
  • <layer>
  • <link>
  • <ilayer>
  • <meta>
  • <object>

可能這裏最讓人不能理解的是<img>。但是,看過下列代碼後,就應該明白其危險性了。

< img src ="javascript:alert('hello');" >
< img src ="java script:alert('hello');" >
< img src ="java script:alert('hello');" >



通過<img>標籤是有可能導致Javascript執行的,這樣攻擊者就可以做他想僞裝的任何事情。

關於<style>也是一樣:

< style TYPE ="text/javascript" > ...
   alert('hello');
</ style >



參考:

HOW TO: 使用 Visual C# .NET 在 ASP.NET 中創建自定義錯誤報告
http://support.microsoft.com/kb/306355/zh-cn

HttpRequestValidationException 類 (System.Web)
http://msdn2.microsoft.com/zh-cn/library/system.web.httprequestvalidationexception(VS.80).aspx


MSDN: How To: Prevent Cross-Site Scripting in ASP.NET
http://msdn2.microsoft.com/en-us/library/ms998274.aspx

推薦大家閱讀微軟關於.Net安全的一系列文章:
http://msdn2.microsoft.com/en-us/library/ms978512.aspx

關於跨站腳本攻擊請參考:

Wikipedia 維基大百科全書
http://en.wikipedia.org/wiki/Cross_site_scripting

Xfocus
http://www.xfocus.org/articles/200607/874.html

Google
http://www.google.com/search?q=%E8%B7%A8%E7%AB%99%E8%84%9A%E6%9C%AC%E6%94%BB%E5%87%BB

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章