從客戶端(...)中檢測到有潛在危險的Request.Form 值的處理辦法

asp.net開發中,常常遇到「從客戶端檢測到有潛在危險的Request.Form 值」錯誤提示,不少人給出的解決方案是:javascript

一、web.config文檔<system.web>後面加入這一句: <pages validaterequest="false"/> 
示例: 
<?xml version="1.0" encoding="gb2312" ?> 
<configuration> 
<system.web> 
<pages validaterequest="false"/> 
</system.web> 
</configuration>html

二、在*.aspx文檔頭的page中加入validaterequest="false",示例以下: 
<%@ page validaterequest="false" language="c#" codebehind="index.aspx.cs" autoeventwireup="false" inherits="mybbs.webform1" %> 
 java

其實這樣作是不正確的,會給程序安全帶來風險。程序員

  ASP.Net 1.1後引入了對提交表單自動檢查是否存在XSS(跨站腳本攻擊)的能力。當用戶試圖用之類的輸入影響頁面返回結果的時候,ASP.Net的引擎會引起一個 HttpRequestValidationExceptioin。這是ASP.Net提供的一個很重要的安全特性。由於不少程序員對安全沒有概念,甚至都不知道XSS這種攻擊的存在,知道主動去防禦的就更少了。ASP.Net在這一點上作到默認安全。這樣讓對安全不是很瞭解的程序員依舊能夠寫出有必定安全防禦能力的網站。web

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

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

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

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

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

protected void Page_Error(object sender, EventArgs e)
{
Exception ex = Server.GetLastError();
if (HttpContext.Current.Server.GetLastError() is HttpRequestValidationException)
{
HttpContext.Current.Response.Write("請輸入合法的字符串【<a href=\"javascript:history.back(0);\">返回</a>】");
HttpContext.Current.Server.ClearError();
}
}

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

  這段代碼很簡單,因此我但願全部不是真的要容許用戶輸入之類字符的朋友,千萬不要隨意的禁止這個安全特性,若是隻是須要異常處理,那麼請用相似於上面的代碼來處理便可。

  而對於那些經過 明確禁止了這個特性的程序員,本身必定要明白本身在作什麼,並且必定要本身手動的檢查必須過濾的字符串,不然你的站點很容易引起跨站腳本攻擊。

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

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

  根據微軟的建議,咱們應該採起安全上稱爲「默認禁止,顯式容許」的策略。

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

  而後,咱們再對咱們所感興趣的、而且是安全標籤,經過Replace()進行替換。好比,咱們但願有""標籤,那麼咱們就將""顯式的替換回""。

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;", "</b>");
sb.Replace("&lt;i&gt;", "<i>");
sb.Replace("&lt;/i&gt;", "</i>");
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');">

相關文章
相關標籤/搜索