转--Securing your ASP.NET MVC

原文:http://blogs.msdn.com/b/rickandy/archive/2012/03/23/securing-your-asp-net-mvc-4-app-and-the-new-allowanonymous-attribute.aspx

SSL:

Many web sites log in via SSL and redirect back to HTTP after you’re logged in, which is absolutely the wrong thing to do.  Your login cookie is just as secret as your username + password, and now you’re sending it in clear-text across the wire.  Besides, you’ve already taken the time to perform the handshake and secure the channel (which is the bulk of what makes HTTPS slower than HTTP) before the MVC pipeline is run, so redirecting back to HTTP after you’re logged in won’t make the current request or future requests much faster.  If you’re hosting static content (youtube for example), change your embedding to use HTTPS rather than HTTP. If you drop down to HTTP from HTTPS without correctly signing out (see http://msdn.microsoft.com/en-us/library/system.web.security.formsauthentication.signout.aspx ) your username + password is wide open. It's not enough to call FormsAuthentication.SignOut().

For information on setting up SSL on ASP.NET MVC, see my blog entry Better, Faster, Easier SSL testing for ASP.NET MVC & WebForms. IIS Express (the new default web server for Visual Studio 11) supports SSL.

To protect against these threats, you can apply the RequireHttpsAttribute  to the global filters collection in the global.asax file.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new System.Web.Mvc.AuthorizeAttribute());
    filters.Add(new RequireHttpsAttribute());
}

Over-Posting Model Data

Suppose you have a blog and your comments are represented by this object from your ORM system:

public class Comment
{
    public int ID { get; set; }      // Primary key
    public int BlogID { get; set; }  // Foreign key
    public Blog Blog { get; set; }   // Foreign entity
    public string Name { get; set; }
    public string Body { get; set; }
    public bool Approved { get; set; }
}

And this is the Create view for the comments to be entered by users:

 <div class="editor-label">
     @Html.LabelFor(model => model.Name)
 </div>
 <div class="editor-field">
     @Html.EditorFor(model => model.Name)
     @Html.ValidationMessageFor(model => model.Name)
 </div>

 <div class="editor-label">
     @Html.LabelFor(model => model.Body)
 </div>
 <div class="editor-field">
     @Html.EditorFor(model => model.Body)
     @Html.ValidationMessageFor(model => model.Body)
 </div>

The intention for comments is that they won't be approved by default. The blog owner will come along later and use the UI to approve all the non-spam comments.

What happens if the bad guy includes "Approved=true" in the form post? The model binder will happily set the Approved property to true. That's definitely not what you intended! It actually gets worse: if the bad guy guesses your entity object is called Blog, he might try posting values into fields like Blog.Body and actually be able to overwrite the body of the blog post. This is a potential disaster!

How can you prevent this? 

  1. The preferred approach is to pass a view model that doesn’t contain any fields you don’t want exposed  ( Blog and Approved in our sample. )
  2. You could use the Bind attribute, either on the Comment type or on the Comment action parameter, to indicate which properties are approved or disapproved for binding.  The "white-list" approach is preferred so that only the named properties can be bound to, rather than the "black-list" approach (which excludes specific properties, and allows binding to everything else). With the black-list approach, you have to remember to black-list new properties added to the model.
  3. Use the (Try)UpdateModel methods on Controller have overloads which accept white-/black-list parameter lists to tell the system which properties are eligible for binding.

Under-Posting Model Data

Under-posting is also a security risk. See Brad Wilson blog entry Input Validation vs. Model Validation in ASP.NET MVC which discusses security issues related to model validation. Although the blog was written in the ASP.NET MVC 2 timeframe, the security details apply to ASP.NET MVC 4 versions.

 

I'd recommend setting RouteExistingFiles back to false (so that Routing and the MVC pipeline don't handle these requests, IIS and ASP.NET core do). Put all of the files for which you want to deny access into a single folder, then drop a Web.config into that folder:

<configuration>
  <system.web>
    <authorization>
      <deny users="*"/>
    </authorization>
  </system.web>
</configuration>

This will prevent IIS and ASP.NET from serving these files directly.

posted @ 2014-11-01 23:17  英雄饶命啊  阅读(178)  评论(0)    收藏  举报