共用方式為


防止 JavaScript 插入式攻擊 (C#)

作者 :Stephen Walther

防止發生 JavaScript 插入式攻擊和跨網站腳本攻擊。 在本教學課程中,Stephen Walther 說明如何透過 HTML 編碼內容輕鬆地破壞這些類型的攻擊。

本教學課程的目標是說明如何在 ASP.NET MVC 應用程式中防止 JavaScript 插入式攻擊。 本教學課程討論兩種方法來防禦您的網站,以防止 JavaScript 插入式攻擊。 您將瞭解如何藉由編碼所顯示的資料來防止 JavaScript 插入式攻擊。 您也會瞭解如何藉由編碼您接受的資料來防止 JavaScript 插入式攻擊。

什麼是 JavaScript 插入式攻擊?

每當接受使用者輸入並重新顯示使用者輸入時,就會將網站開啟至 JavaScript 插入式攻擊。 讓我們檢查對 JavaScript 插入式攻擊開放的具體應用程式。

假設您已建立客戶意見反應網站, (請參閱圖 1) 。 客戶可以流覽網站,並使用您的產品輸入其體驗的意見反應。 當客戶提交意見反應時,意見反應會在意見反應頁面上重新顯示。

客戶意見反應網站

圖 01:客戶意見反應網站 (按一下即可檢視全尺寸影像)

客戶意見反應網站會在清單 1 中使用 controller 。 這 controller 包含兩個名為 Index() 和 的 Create() 動作。

清單 1 – HomeController.cs

using System;
using System.Web.Mvc;
using CustomerFeedback.Models;

namespace CustomerFeedback.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          private FeedbackDataContext db = new FeedbackDataContext();

          public ActionResult Index()
          {
               return View(db.Feedbacks);
          }

          public ActionResult Create(string message)

          {
               // Add feedback
               var newFeedback = new Feedback();
               newFeedback.Message = message;
               newFeedback.EntryDate = DateTime.Now;
               db.Feedbacks.InsertOnSubmit(newFeedback);
               db.SubmitChanges();

               // Redirect
               return RedirectToAction("Index");
          }
     }
}

方法 Index() 會顯示檢 Index 視。 此方法會使用LINQ to SQL查詢) ,從 (資料庫擷取意見反應,將所有先前的客戶意見反應傳遞至 Index 檢視。

方法 Create() 會建立新的 Feedback 專案,並將其新增至資料庫。 客戶在表單中輸入的訊息會傳遞至 Create() 訊息參數中的 方法。 系統會建立意見反應專案,並將訊息指派給 Feedback 專案的 Message 屬性。 意見反應專案會透過 DataContext.SubmitChanges() 方法呼叫提交至資料庫。 最後,訪客會重新導向回 Index 顯示所有意見反應的檢視。

Index 視包含在清單 2 中。

清單 2 – Index.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="CustomerFeedback.Views.Home.Index"%>

<%@ Import Namespace="CustomerFeedback.Models" %>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
     <h1>Customer Feedback</h1>
     <p>
          Please use the following form to enter feedback about our product.
     </p>

     <form method="post" action="/Home/Create">

          <label for="message">Message:</label>
          <br />
          <textarea name="message" cols="50" rows="2"></textarea>
          <br /><br />
          <input type="submit" value="Submit Feedback" />
     </form>

     <% foreach (Feedback feedback in ViewData.Model)
     {%>
          <p>
          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=feedback.Message%>
          </p>
     <% }%>

</asp:Content>

Index 視有兩個區段。 頂端區段包含實際的客戶意見反應表單。 底部區段包含 For.。每個迴圈會迴圈查看所有先前的客戶意見反應專案,並顯示每個意見反應專案的 EntryDate 和 Message 屬性。

客戶意見反應網站是簡單的網站。 不幸的是,網站已開放 JavaScript 插入式攻擊。

假設您在客戶意見反應表單中輸入下列文字:

<script>alert("Boo!")</script>

此文字代表顯示警示訊息方塊的 JavaScript 腳本。 有人將此腳本提交至意見反應表單之後,訊息 Boo!每當任何人在未來造訪客戶意見反應網站時,都會顯示 (請參閱圖 2) 。

JavaScript 插入

圖 02:JavaScript 插入 (按一下即可檢視大小完整的影像)

現在,對 JavaScript 插入式攻擊的初始回應可能是無理。 您可能會認為 JavaScript 插入式攻擊只是一種 表面 攻擊。 您可能認為沒有人可以藉由認可 JavaScript 插入式攻擊來真正做出任何動作。

不幸的是,駭客可以藉由將 JavaScript 插入網站來執行一些真正有趣的事。 您可以使用 JavaScript 插入式攻擊來執行跨網站腳本 (XSS) 攻擊。 在跨網站腳本攻擊中,您會竊取機密使用者資訊,並將資訊傳送至另一個網站。

例如,駭客可以使用 JavaScript 插入式攻擊來竊取其他使用者的瀏覽器 Cookie 值。 如果敏感性資訊 -- 例如密碼、信用卡號碼或社會安全號碼 – 會儲存在瀏覽器 Cookie 中,則駭客可以使用 JavaScript 插入式攻擊來竊取此資訊。 或者,如果使用者在遭到 JavaScript 攻擊遭到入侵的頁面中輸入敏感性資訊,則駭客可以使用插入的 JavaScript 來擷取表單資料,並將它傳送至另一個網站。

請擔心。 請仔細處理 JavaScript 插入式攻擊,並保護您的使用者的機密資訊。 在接下來的兩節中,我們將討論兩種技術,可讓您用來防禦 javaScript 插入式攻擊的 ASP.NET MVC 應用程式。

方法 #1:檢視中的 HTML 編碼

防止 JavaScript 插入式攻擊的一個簡單方法,就是當您在檢視中重新顯示資料時,HTML 編碼網站使用者輸入的任何資料。 清單 3 中的更新 Index 檢視遵循此方法。

清單 3 – Index.aspx (HTML 編碼)

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="CustomerFeedback.Views.Home.Index"%>

<%@ Import Namespace="CustomerFeedback.Models" %>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
     <h1>Customer Feedback</h1>
     <p>
          Please use the following form to enter feedback about our product.
     </p>

     <form method="post" action="/Home/Create">
          <label for="message">Message:</label>
          <br />
          <textarea name="message" cols="50" rows="2"></textarea>
          <br /><br />
          <input type="submit" value="Submit Feedback" />

     </form>

     <% foreach (Feedback feedback in ViewData.Model)
     {%>
          <p>
          <%=feedback.EntryDate.ToShortTimeString()%>
          --
          <%=Html.Encode(feedback.Message)%>
          </p>
     <% }%>

</asp:Content>

請注意,的值 feedback.Message 會在值以下列程式碼顯示之前編碼的 HTML:

<%=Html.Encode(feedback.Message)%>

HTML 編碼字串的意義為何? 當您 HTML 編碼字串時,和 之類的 <> 危險字元會由 和 等 &lt;&gt; HTML 實體參考取代。 因此,當字串 <script>alert("Boo!")</script> 經過 HTML 編碼時,它會轉換成 &lt;script&gt;alert(&quot;Boo!&quot;)&lt;/script&gt; 。 當瀏覽器解譯時,編碼字串不再以 JavaScript 腳本的形式執行。 相反地,您會在圖 3 中取得無損害的頁面。

遭攻擊的 JavaScript 攻擊

圖 03:失敗的 JavaScript 攻擊 (按一下即可檢視完整大小的影像)

請注意,在清單 3 的檢視中 Index ,只會編碼 的值 feedback.Message 。 的值 feedback.EntryDate 未編碼。 您只需要編碼使用者輸入的資料。 因為 EntryDate 的值是在控制器中產生,所以您不需要 HTML 編碼此值。

方法 #2:控制器中的 HTML 編碼

當您在檢視中顯示資料時,您可以先 HTML 編碼資料,再將資料提交至資料庫。 第二種方法是在 controller 清單 4 中採用。

清單 4 – HomeController.cs (HTML 編碼)

using System;
using System.Web.Mvc;
using CustomerFeedback.Models;
namespace CustomerFeedback.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          private FeedbackDataContext db = new FeedbackDataContext();

          public ActionResult Index()
          {
               return View(db.Feedbacks);
          }

          public ActionResult Create(string message)
          {
               // Add feedback
               var newFeedback = new Feedback();
               newFeedback.Message = Server.HtmlEncode(message);
               newFeedback.EntryDate = DateTime.Now;
               db.Feedbacks.InsertOnSubmit(newFeedback);

               db.SubmitChanges();

               // Redirect
               return RedirectToAction("Index");
          }
     }
}

請注意,在將值提交至動作內的 Create() 資料庫之前,訊息的值會經過 HTML 編碼。 當訊息在檢視中重新顯示時,訊息會經過 HTML 編碼,而且不會執行插入訊息中的任何 JavaScript。

一般而言,您應該優先使用本教學課程中討論的第一種方法,而非第二種方法。 第二種方法的問題在於,您最後會在資料庫中使用 HTML 編碼的資料。 換句話說,您的資料庫資料會以有趣的外觀字元來變更。

為什麼這種狀況不正確? 如果您需要在網頁以外的內容中顯示資料庫資料,您就會發生問題。 例如,您無法再輕鬆地在Windows Forms應用程式中顯示資料。

總結

本教學課程的目的是要讓您擔心 JavaScript 插入式攻擊的可能性。 本教學課程討論了兩種方法,可用來防禦 ASP.NET MVC 應用程式,以防止 JavaScript 插入式攻擊:您可以在檢視中將使用者送出資料的 HTML 編碼,或是 HTML 編碼控制器中提交的資料。