防止 JavaScript 插入式攻擊 (VB)
防止 JavaScript 注入攻擊和跨站指令碼攻擊發生在您身上。 在本教學課程中,Stephen Walther 會說明如何透過對內容進行 HTML 編碼來輕鬆擊敗這些類型的攻擊。
本教學課程的目的是要說明如何在 ASP.NET MVC 應用程式中防止 JavaScript 插入式攻擊。 本教學課程討論兩種方法來防禦您的網站,以防止 JavaScript 插入式攻擊。 您將瞭解如何對所顯示的資料進行編碼,以防止 JavaScript 插入式攻擊。 您也會瞭解如何對您接受的資料進行編碼,以防止 JavaScript 插入式攻擊。
什麼是 JavaScript 插入式攻擊?
每當您接受使用者輸入並重新顯示使用者輸入時,網站就會暴露在 JavaScript 插入式攻擊的風險中。 讓我們看看暴露在 JavaScript 插入式攻擊風險中的具體應用程式。
假設您已建立客戶意見反應網站 (請參閱圖 1)。 客戶可以使用您的產品瀏覽網站,並輸入有關其體驗的意見反應。 當客戶提交意見反應時,意見反應會在意見反應頁面上重新顯示。
圖 01:客戶意見反應網站 (按一下以檢視完整大小的圖片)
客戶意見反應網站使用清單 1 中的 controller
。 這個 controller
包含名為 Index()
和 Create()
的兩個動作。
清單 1 – HomeController.vb
Public Class HomeController
Inherits System.Web.Mvc.Controller
Private db As New FeedbackDataContext()
Function Index()
Return View(db.Feedbacks)
End Function
Function Create(ByVal message As String)
' Add feedback
Dim newFeedback As New Feedback()
newFeedback.Message = Server.HtmlEncode(message)
newFeedback.EntryDate = DateTime.Now
db.Feedbacks.InsertOnSubmit(newFeedback)
db.SubmitChanges()
' Redirect
Return RedirectToAction("Index")
End Function
End Class
Index()
方法會顯示 Index
檢視。 此方法會從資料庫擷取意見反應 (使用 LINQ to SQL 查詢) 擷取意見反應,將所有先前的客戶意見反應傳遞至 Index
檢視。
Create()
方法會建立新的意見反應項目,並將其新增至資料庫。 客戶在表單中輸入的訊息會傳遞至訊息參數中的 Create()
方法。 系統會建立意見反應項目,並將訊息指派給意見反應項目的 Message
屬性。 意見反應項目會透過 DataContext.SubmitChanges()
方法呼叫提交至資料庫。 最後,訪客會重新導向回顯示所有意見反應的 Index
檢視。
Index
檢視包含在清單 2 中。
清單 2 – Index.aspx
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="CustomerFeedback.Index"%>
<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>
<% For Each feedback As CustomerFeedback.Feedback In ViewData.Model%>
<p>
<%=feedback.EntryDate.ToShortTimeString()%>
--
<%=feedback.Message%>
</p>
<% Next %>
</asp:Content>
Index
檢視有兩個區段。 頂端區段包含實際的客戶意見反應表單。 底部區段包含.. 每個迴圈都會循環處理所有先前的客戶意見反應項目,並顯示每個意見反應項目的 EntryDate 和 Message 屬性。
客戶意見反應網站是簡單的網站。 不幸的是,網站會暴露在 JavaScript 插入式攻擊的風險中。
假設您在客戶意見反應表單中輸入下列文字:
<script>alert("Boo!")</script>
此文字代表顯示警示訊息方塊的 JavaScript 指令碼。 有人將此指令碼提交至意見反應表單之後,每當任何人在未來造訪客戶意見反應網站時,就會出現訊息「Boo!」 (請參閱圖 2)。
圖 02:JavaScript 插入式攻擊 (按一下以檢視完整大小的圖片)
現在,您對 JavaScript 插入式攻擊的初始回應可能有點冷漠。 您可能會認為 JavaScript 插入式攻擊只是一種竄改攻擊。 您可能相信沒有人能藉由實施 JavaScript 插入式攻擊來執行任何真正邪惡的事情。
不幸的是,駭客可以藉由將 JavaScript 插入網站來做一些真正邪惡的事情。 JavaScript 插入式攻擊可用來執行跨網站指令碼 (XSS) 攻擊。 跨網站指令碼攻擊會竊取機密使用者資訊,並將資訊傳送至另一個網站。
例如,駭客可以使用 JavaScript 插入式攻擊,從其他使用者竊取瀏覽器 Cookie 的值。 如果密碼、信用卡號碼或社會安全號碼等敏感性資訊儲存在瀏覽器 Cookie 中,則駭客可以使用 JavaScript 插入式攻擊來竊取此資訊。 或者,如果使用者在已遭 JavaScript 攻擊入侵之頁面的表單欄位中輸入敏感性資訊,則駭客可以使用插入的 JavaScript 來擷取表單資料,並將其傳送至另一個網站。
請務必警惕。 認真處理 JavaScript 插入式攻擊,並保護您的使用者的機密資訊。 在接下來的兩節中,我們將討論兩種技術,可讓您避免 ASP.NET MVC 應用程式遭到 JavaScript 插入式攻擊。
方法 1:檢視中的 HTML 編碼
防止 JavaScript 插入式攻擊的一個簡單方法,是當您在檢視中重新顯示資料時,對網站使用者輸入的任何資料進行 HTML 編碼。 清單 3 中更新的 Index
檢視採用此方法。
清單 3 – Index.aspx
(經過 HTML 編碼)
<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="CustomerFeedback.Index"%>
<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>
<% For Each feedback As CustomerFeedback.Feedback In ViewData.Model%>
<p>
<%=feedback.EntryDate.ToShortTimeString()%>
--
<%=Html.Encode(feedback.Message)%>
</p>
<% Next %>
</asp:Content>
請注意,feedback.Message
的值在以下列程式碼顯示之前,會先經過 HTML 編碼:
<%=Html.Encode(feedback.Message)%>
對字串進行 HTML 編碼的意義為何? 當您對字串進行 HTML 編碼時,<
和 >
之類的危險字元會由 <
和 >
等 HTML 實體參考取代。 因此,當字串 <script>alert("Boo!")</script>
經過 HTML 編碼時,會轉換成 <script>alert("Boo!")</script>
。 當瀏覽器解譯經過編碼的字串時,字串就不會再以 JavaScript 指令碼的形式執行。 相反地,您會取得圖 3 中的無害頁面。
圖 03:JavaScript 攻擊失敗 (按一下以檢視完整大小的圖片)
請注意,在清單 3 的 Index
檢視中,只有 feedback.Message
的值會經過編碼。 feedback.EntryDate
的值不會經過編碼。 您只需要對使用者輸入的資料進行編碼。 由於 EntryDate 的值是在控制器中產生,因此您不需要對此值進行 HTML 編碼。
方法 2:控制器中的 HTML 編碼
您可以先對資料進行 HTML 編碼,再將資料提交至資料庫,而不是在檢視中顯示資料時對資料進行 HTML 編碼。 在清單 4 的 controller
案例中,會採用第二種方法。
清單 4 – HomeController.cs
(經過 HTML 編碼)
Public Class HomeController
Inherits System.Web.Mvc.Controller
Private db As New FeedbackDataContext()
Function Index()
Return View(db.Feedbacks)
End Function
Function Create(ByVal message As String)
' Add feedback
Dim newFeedback As New Feedback()
newFeedback.Message = Server.HtmlEncode(message)
newFeedback.EntryDate = DateTime.Now
db.Feedbacks.InsertOnSubmit(newFeedback)
db.SubmitChanges()
' Redirect
Return RedirectToAction("Index")
End Function
End Class
請注意,在 Create()
動作內將值提交至資料庫之前,訊息的值會經過 HTML 編碼。 在檢視中重新顯示訊息時,訊息會經過 HTML 編碼,而且不會執行訊息中插入的任何 JavaScript。
一般而言,您應該優先使用本教學課程中討論的第一種方法,而不是第二種方法。 第二種方法的問題是,您最終會在資料庫中對資料進行 HTML 編碼。 換句話說,您的資料庫資料會以外觀奇特的字元來抹除。
這樣有何壞處? 如果您需要在網頁以外的內容中顯示資料庫資料,您將會遇到問題。 例如,您無法再輕鬆地在 Windows Forms 應用程式中顯示資料。
摘要
本教學課程的目的是警惕您 JavaScript 插入式攻擊的可能後果。 本教學課程討論了兩種方法,可用來保護您的 ASP.NET MVC 應用程式,以防止 JavaScript 插入式攻擊:您可以在檢視中對使用者提交的資料進行 HTML 編碼,或者您也可以在控制器中對使用者提交的資料進行 HTML 編碼。