防止JavaScript注入攻击

时间:2022-03-14 03:54:09

这篇文章主要介绍在ASP.NET MVC应用程序中如何防止JavaScript注入攻击。这篇文章讨论了两种防止JavaScript攻击的方法:
在显示数据的时候,通过使用Encoding来防止攻击
在接收到数据的时候,通过使用Encoding防止攻

一、什么是JavaScript注入攻击(原创:灰灰虫的家 http://hi.baidu.com/grayworm
在我们接收用户输入或在页面显示用户输入的数据时,我们的网站默认是向JavaScript注入攻击敞开了大门。让我们看看我们的Web应用程序如何被JavaScript攻击。
假设我们创建了一个用户反馈的网站,用户可以访问该网站并填写产品使用的反馈信息。当用户填写完反馈信息后,程序会把用户的反馈信息显示在页面上。

防止JavaScript注入攻击


《图1 》
用户反馈网站的控制器代码如下所示,其中包含两个动作Index()和Create()
Listing 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()方法用来向视图传递显示数据的,这个方法检索表中所有的用户反馈信息,并传递给页面显示。
Create()创建一个新的用户返回,并把它加到数据库中。用户在表单中输入的数据会以message参数被传递到Create()方法中。我们通过调用DataContext.SubmitChanges()方法把页面返回数据送到数据库中去。最后调用Index()动作,显示所有的用户反馈数据。

Index视图代码如下
Listing 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视图代码可以分成两部分来看待,上面的部分是用户输入的表单,下面的部分是foreach…loop循环,迭代所有的用户返馈信息,显示EntryDate和Message两个字段的信息。
用户返馈网站很简单,但这个网站很容易被JavaScript攻击。
如果用户输入的反馈内容是
<script>alert(“Boo!”)</script> 
那这段文本在显示的时候会在页面上弹出一个消息框,以后任何人在访问这个网站的时候,在显示用户的反馈信息时都会弹出这个对话框。

防止JavaScript注入攻击


《图2》
可能你对上面的JavaScript注入感觉没什么大不了的,好像它只能对我们的界面显示产生影响,它并不会给我们的网站的安全性还来真正可怕的影响。不幸的是,一个黑客足可以使用JavaScript攻击来给你的网站带来可怕的事情。它可以使用JavaScript注入执行Cross-Site Scripting攻击。Cross-Site Scripting攻击就是盗窃用来的机密信息并发送到别的网站上去。比如:黑客可以使用JavaScript注入攻击从客户机的Cookie中盗取敏感信息(密码、信用卡号、社保账号等),或者把其它用户表单中输入的机密数据发送到其它网站上去。

二、解决方法一:在视图中使用Html.Encode显示数据(原创:灰灰虫的家 http://hi.baidu.com/grayworm
防止JavaScript注入攻击的一个简单方法就是当显示用户输入的数据时,使用Html.Encode()方法把数据库中的数据编码显示。我们修改后的Index视图代码如下:
Listing 3 – Index.aspx (HTML Encoded)
<%@ 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.Encode()方法进行了编码。
<%=Html.Encode(feedback.Message)%> 
HTML Encode的意思就是,把一些危险的字符如<和>替换为&lt;和&gt;。
所以当<script>alert("Boo!")</script>被Encode后,就会变为&lt;script&gt;alert(&quot;Boo!&quot;)&lt;/script&gt;。被编码后的字符串就不再是一个可执行的JavaScript代码了,它会正常显示在页面上。如下图所示

防止JavaScript注入攻击


《图3》
上面的代码中我们只对feedback.Message进行了编码,而feedback.EntryDate没有进行编码。因为feedback.EntryDate是控制器生成的,不会有危险性,而feedback.Message是用户输入的,所以为了安全其见我们需要对其进行编码

三、解决方法二:在控制器中对HTML数据进行编码(原创:灰灰虫的家 http://hi.baidu.com/grayworm
除了在显示的时候对用户反馈的信息进行编码显示,我们还可以在控制器接收到用户提交的数据后进行编码,然后把编码后的数据送到数据库中
下面的代码,是我们在控制器中对用户输入的数据进行编码
Listing 4 – HomeController.cs (HTML Encoded)
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标记,即会产生一些古怪难以理解的数据,这些数据在WEB页面中显示会变得正常,但在WinForms应用程序中显示时会搞成一团糟。

总结
这篇文章主要讨论了JavaScript攻击,并提出在ASP.NET MVC应用程序中两种解决方案:
在显示数据的时候,通过使用Encoding来防止攻击
在接收到数据的时候,通过使用Encoding防止攻
(原创:灰灰虫的家 http://hi.baidu.com/grayworm