JavaScript And Ajax(呈現腳本塊、腳本注入攻擊)


呈現腳本塊

       目前為止的 js 都是直接插入頁面 .aspx 部分的靜態 <script> 塊。然而,使用公開 ClientScriptManager 對象的 Page.ClientScript 屬性呈現腳本通常更加靈活。

       ClientScriptManager 提供了幾個管理腳本塊的有用方法,其中兩個最有用的方法如下:

  • RegisterClientScriptBlock() :把腳本塊寫到 Web 表單的開始,在 <form runat=”server”> 標簽后。適合響應 js 事件而被調用的函數使用。這樣的 <script> 塊可以放在任意地方,放在 Web 表單開頭只是出於習慣並使它們容易被找到
  • RegisterStartupScript() :把腳本塊寫到 Web 表單的結尾,在結束標簽 </form> 之前。用於添加那些頁面加載時立刻執行的 js 代碼。這些代碼可能操縱頁面上的其他控件,所有放在 Web 表單的結尾比較安全。

       使用這 2 個方法,需要指定腳本塊的鍵名。唯一的鍵名,好處是能保證 ASP.NET 不會把相同的腳本函數添加多次。例如 ASP.NET 驗證控件,每個控件都要使用一些驗證函數,但是讓每個控件都添加重復的 <script> 塊並沒有意義。但當調用 RegisterClientScriptBlock() 時,每個控件都使用相同的鍵名,ASP.NET 知道它們是重復的定義,所以只呈現一份單一副本。

 

       下面的代碼注冊一個 confirmSubmit() 的 js 函數,通過 onsubmit 特性附加到表單上:

protected void Page_Load(object sender, EventArgs e)
{
    string script = @"<script type='text/javascript'>
        function confirmSubmit(){
            var msg = 'Are you sure you want to submit this data?';
            return confirm(msg);
        }
    </script>";
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Confirm", script);
    form1.Attributes.Add("onsubmit", "return confirmSubmit();");
}

       本示例並沒有從 RegisterClientScriptBlock() 方法中受益。但是,使用 js 創建一個自定義控件時,ClientScriptMananger 方法就非常重要了!

 

 

腳本注入攻擊

       開發人員並非不能意識到頁面中的安全問題,只是因為很多常見的危險(包括 腳本注入 和 SQL注入)會在不經意間發生。

       一個常施加於網頁的攻擊是腳本注入攻擊。用戶提交惡意標簽或腳本代碼(一般通過 TextBox 控件之類的簡單控件),然后呈現到 HTML 頁面,這時就會發生腳本注入攻擊。如果用戶提供的數據被保存到數據庫並插入到其他用戶使用的頁面,攻擊可以影響網站所有用戶的操作

       腳本注入攻擊的基本技術是客戶端提交嵌入了腳本標簽的內容。這些腳本標簽可以包括 <script>、<object>、<applet> 和<embed>。雖然應用程序可以具體檢查這些標簽並用 HTML 編碼來使用無害的 HTML 實體代替這些標簽,但是通常不會執行基本驗證。

 

請求驗證

       腳本注入攻擊是所有 Web 開發人員都關注的,無論他們使用的是 ASP.NET、ASP 還是其他 Web 開發技術。ASP.NET 包含一個設計用於自動防止腳本注入攻擊的功能,叫做請求驗證。它檢查回傳的表單輸入,如果發現潛在的惡意標簽(如 <script>),就報告一個錯誤。實際上,請求驗證禁止所有非數值的標簽,包括 HTML 標簽( 如<b> 或 <img>等)和不正確的標簽(如<abcd>)。

       創建一個頁面可測試請求驗證功能:

image

       現在嘗試提交的話,如果是本地運行代碼,可以看到下面的錯誤詳細信息(遠程只會看見一般的錯誤頁面):

image

 

禁用請求驗證

       當然,有時,請求驗證規則有點太嚴格了。例如,有的程序確實需要用戶輸入 HTML 標簽或者 XML 數據塊。例如用戶要提交一個拍賣列表或者銷售廣告的格式化 HTML 塊的 Web 應用。

       這些情況下,你可以 2 步禁用請求驗證

       首先,設置 Page 指令,不過這還不能立刻帶來變化。因為 ASP.NET 4 改變了請求驗證的工作方式。現在它在頁面處理生命周期之前被應用

<%@ Page ValidateRequest="false" ... %>

       其次,配置 web.config 文件,告訴 ASP.NET 4 恢復以前版本的驗證行為:

<system.web>
    <httpRuntime requestValidationMode="2.0"/>
    ...
</system.web>

       現在,想象一下如果使用這段代碼在標簽里顯示用戶提供的值會發生什么:

protected void Button1_Click(object sender, EventArgs e)
{
    lblInfo.Text = "You entered: " + txtInput.Text; 
}

image 

image

       也可以修改 web.config 文件來禁用整個 Web 應用程序的請求驗證。設置或增加 <pages> 元素的 validateRequest 屬性:

<system.web>
    <pages validateRequest="false">
    <httpRuntime requestValidationMode="2.0"/>
    ...
</system.web>

 

       腳本注入攻擊中的腳本總是在客戶端執行。但是,這並不意味着它僅僅限於單一用戶!大多情況下,用戶提供的數據被保存到一個數據庫之類的地方,並且能夠被其他用戶瀏覽。例如,一個用戶把腳本塊作為業務名稱加入業務注冊表,其他請求完整業務注冊表的用戶就會受到影響。

       在請求驗證被關閉的情況下,為了阻止腳本注入攻擊的發生,你需要在顯示內容前使用 Server 對象顯式地編碼要顯示的內容:

protected void Button1_Click(object sender, EventArgs e)
{
    lblInfo.Text = "You entered: " + Server.HtmlEncode(txtInput.Text);
}

image

 

擴展請求驗證

       對於絕大部分 Web 應用程序,ASP.NET 請求驗證能夠很好的滿足其驗證需要。但是在某些情況下,你可能需要選擇讓一些通常會被拒絕的值通過驗證或者要增加其他要被禁止的值,此時,需要通過自定義代碼來擴展請求驗證系統。(如果面臨完全禁用請求驗證和通過代碼增加例外的兩難選擇,通常增加例外是更好的選擇!否則,你的程序對各種腳本攻擊或其他損害毫無招架之力)。

       為了擴展請求驗證系統,需要派生 System.Web.Util.RequestValidator 類並重寫 IsValidRequestString() 方法:

public class CustomRequestValidator : System.Web.Util.RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context, 
        string value, RequestValidationSource requestValidationSource, 
        string collectionKey, out int validationFailureIndex)
    {
        ...
    }
}

       IsValidRequestString() 方法接受 5 個參數:

  1. context 。請求的 HttpContext,通過它可以訪問內置的 ASP.NET 對象,如 Request、Response、Application、Server、Session 和 Cache。
  2. value 。它是要進行驗證的字符串文本
  3. requestValidationSource 。它使用枚舉 RequestValidationSource 來標識要驗證的信息類型。可能的值包括 Cookies、File、Form、Headers、Path 和 QueryString。
  4. collectionKey 。如果數據源來自某個集合,collectionKey 返回用於索引值的鍵值。例如,對於表單數據,collectionKey 和回發值的輸入控件相對應。
  5. validationFailureIndex 。如果驗證執行成功,validationFailureIndex 應該設置為 0 並且 IsValidRequestString() 返回 true。如果驗證失敗,IsValidRequestString() 方法返回 false,而 validationFailureIndex 指向字符串中非法數據開始的位置。

       通過這些信息,可以很方便的創建改變 ASP.NET 內置行為的應急的驗證方法。

       下面的示例里,驗證器檢查是否在進行表單驗證。如果不是,驗證器觸發默認的實現。如果是,則搜索回發輸入中的 <script> 標記。如果包含就拒絕該值,但同時接收其他合法的值,這使它的驗證行為要比 ASP.NET 默認驗證更為寬松

public class CustomRequestValidator : System.Web.Util.RequestValidator
{
    protected override bool IsValidRequestString(HttpContext context,
        string value, RequestValidationSource requestValidationSource,
        string collectionKey, out int validationFailureIndex)
    {
        if (requestValidationSource == RequestValidationSource.Form)
        {
            int errorIndex = value.ToLower().IndexOf("<script>");
            if (errorIndex != -1)
            {
                validationFailureIndex = errorIndex;
                return false;
            }
            else
            {
                validationFailureIndex = 0;
                return true;
            }
        }
        else
        {
            return base.IsValidRequestString(context, value,
                requestValidationSource, collectionKey, out validationFailureIndex);
        }
    }
}

       需要在 web.config 文件中注冊它才能使用:

<system.web>
  <httpRuntime requestValidationType="CustomRequestValidator"/>
  ...
</system.web>

 

       這個示例只是簡單演示了自定義驗證是如何工作的。但是,對於如何學會通過自定義代碼加入或多或少的驗證已經足夠了。

       如果要增強標准 ASP.NET 驗證,最好把你的實現添加到默認的實現鏈里。驗證值通過你的檢查后,可以繼續調用基類的 IsValidRequestString() 來執行額外的內置檢查


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM