Security Tip: Blocking Access to ASP.NET MVC Views Using Alternative View Engines

asp.net mvc, asp.net, code 0 comments suggest edit

When you create a new ASP.NET MVC project using our default templates, one of the things you might notice is that there is a web.config file within the Views directory. This file is there specifically to block direct access to a view.

Let’s look at the relevant sections.

For IIS 6 (and Cassini)

<add path="*.aspx" verb="*" 
  type="System.Web.HttpNotFoundHandler"/>
 

For IIS 7

<add name="BlockViewHandler" path="*.aspx" verb="*" 
  preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>

What these sections do is block all access to any file with the .aspx extension within the Views directory (or subdirectories). Note that access is blocked by mapping these file extensions to the HttpNotFoundHandler, so that a 404 error is returned when trying to access a view directly.

This works great if you are using all the ASP.NET MVC defaults, but what if you’re using an alternative view engine such as NHaml or NVelocity? It turns out you can directly request the view and see the code.

You’ll want to make sure to add extra lines within this web.config file with the appropriate file extensions. For example, if I were using NVelocity, I might add the following (in bold).

For IIS 6 (and Cassini)

<add path="*.aspx" verb="*" 
  type="System.Web.HttpNotFoundHandler"/>
<add path="*.vm" verb="*" 
  type="System.Web.HttpNotFoundHandler"/>
 

For IIS 7

<add name="BlockViewHandler" path="*.aspx" verb="*" 
  preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
<add name="BlockViewHandler" path="*.vm" verb="*" 
  preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>

You might be wondering why we don’t block access to all files within the Views directory. Excellent question! In part, because the Views directory is a common place to put other static content such as images, pdfs, audio files, etc… and we decided not to prevent that option.

However, we’re open to suggestions. We do have a content directory in the default template. We could consider requiring putting static files in there or in another directory other than Views. I’m not sure how people would feel if they couldn’t put assets intended to support Views within the Viewsfolder.

Technorati Tags: aspnetmvc,security,view engines

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.

Comments

avatar

21 responses

  1. Avatar for Steven Harman
    Steven Harman June 25th, 2008

    w/r/t blocking direct access to everything in the /views/ directory... I don't feel too strongly one way or the other, but I don't think requiring someone using a custom view engine to add those web.config keys is a lot to expect. As long as that step is well understood, of course.
    However, I totally get the argument for requiring all static content to live in the /content/ directory. Either way, I'd say pick a convention and go with it, allowing others to choose another route if/when they see fit.
    Alternatives/choice is king! :)

  2. Avatar for mark
    mark June 25th, 2008

    Any way we can programmatically point to any view path in the controller? similar to the Page.LoadControl(string).
    Or an attribute in the controller class that specify the location of the views for that controller.
    I guess anything that is configurable and not static.
    Thanks

  3. Avatar for haacked
    haacked June 25th, 2008

    @Steven my concern is that while developing a custom view engine is a very advanced scenario, using one is not necessarily. And there's no way we can create an "affordance" that would indicate that if you're choosing to use this alternate view engine, you also need to remember to update web.config. That'll be something a LOT of people will forget.

  4. Avatar for Wyatt Barnett
    Wyatt Barnett June 25th, 2008

    I'm squarely in the "static content belongs on a different domain, in a separate app and arguably on a different box" school of thought. So I wholeheartedly support limiting the /views folder to actual renderable views and pushing the content elsewhere.

  5. Avatar for Neal Blomfield
    Neal Blomfield June 25th, 2008

    My thinking may be a little backwards wrt ASP.NET MVC (I still use monorail), but isn't the views directory really a directory of templates through which the views are rendered and therefore shouldn't containing anything but templates?
    IMHO use a content directory to separate stuff that the browser will request directly from the stuff that the browser will receive indirectly (the views).

  6. Avatar for Al
    Al June 25th, 2008

    I'd be reluctant to require people put files in a given place, if I want to put files under views - I thnk I should be able to.
    I'd be more inclinded to make sure that sensible defaults are in place to stop accidents happening, ie by default it might be appropriate to block the views folder using a web.config option but if I choose to remove that, I'm doing so by my choice.

  7. Avatar for Lance Fisher
    Lance Fisher June 25th, 2008

    I think it makes sense to put all static content in the content directory or on a different domain, and not in the Views directory. I didn't even realize you could put it there. If you blocked the views directory by default, I think it would help out the problem with showing empty Views during a debug. You know, F5, then you get an ASP.NET error because you're looking at a view page directly and not hitting the routing engine.
    Go with the convention of putting static content in the content folder, and if the developer wants to change it to the views folder, he can modify the web.config. If he's using a different view engine, the new view engine should help him out with the configuration, or utilize the same convention.

  8. Avatar for John Walker
    John Walker June 25th, 2008

    I know there have been big changes in IIS7, but it concerns me a bit that the web.config file has to be different compared to IIS6. As the change from IIS6 to 7 occurs, there's sure to be some grief. Sorry for the non-MVC comment, but this is the first time I've grokked this as a possibility.

  9. Avatar for Boersnoes
    Boersnoes June 25th, 2008

    I vote Content folder. But at the same time, I feel some descent support should be provided out of the box to easely access this static content.
    When you start using user controlls that don't know where they will be rendered in the file hierarchy on compile time, it is somewhat bothersome to reference the content folder (how many "../../" should I put?)
    Currently I use a custom extention to the HTMLHelper I derived from a podcast (I think Rob's) that gives me a Html.CssUrl(cssName), a Html.PictureUrl(picName), a Html.JavaScriptUrl(jsUrl) etc.

  10. Avatar for Daniel Draper
    Daniel Draper June 25th, 2008

    I think the view folder should contain just that "Views" any assets such as images, movies, audio, etc should be placed in the content folder. The content folder however should be broken into appropriate sub folders.
    If you are worried about a relative path Boersnoes then just use the base tag or a custom funtion to acheive a similar outcome.
    I think Al has a good point by making it optional but by default the programmer uses the content directory.

  11. Avatar for Dragan Panjkov
    Dragan Panjkov June 25th, 2008

    I agree with others. Content folder should be used for static content. In this way Views could be reserved only for View files, independently of View Engine used, not to repeat others.

  12. Avatar for Ang3lFir3
    Ang3lFir3 June 25th, 2008

    I will have to agree with others that I strongly believe in keeping all my static content in the content folder or some other location. The Views folder to me is simply the location of the templates for rendering views. Also since many assets belong to many views its just easier for me to keep them organized in a single content location.
    I am with Phil on the idea that using a custom view engine doesn't mean you will remember to take care of this step. The consiquences of not doing it make it dangerous.
    +1 for restricting direct access to all files in the Views dir

  13. Avatar for Anders
    Anders June 26th, 2008

    Another vote for restricting access to the views folder by default and having all the static content in the content folder.

  14. Avatar for Mark Brackett
    Mark Brackett June 26th, 2008

    Another vote for disallowing the entire /Views directory by default. If someone wants to put content in there, then they can edit the web.config to allow it. That's much better than the security hole you're opening up for users of an alternative view engine.
    Why wouldn't you use the existing location and deny tags to deny access? That'd return a 403-Unauthorized error (which is the correct one to choose here, IMO).

  15. Avatar for Andy Miller
    Andy Miller June 26th, 2008

    If you're going to get in the pool, get all the way in!
    Years (...well...months anyway) of anecdotal evidence points to the answer: convention is better. Treat the Views directory just like the bin, App_Code, etc directories and block all access.

  16. Avatar for Damien Guard
    Damien Guard June 27th, 2008

    I'd go with whitelisting .gif, .jpg, .jpeg, .avi, .png, .mov, .mpeg, .css, .htc, .js in views and blocking everything else.
    [)amien

  17. Avatar for EricTN
    EricTN July 2nd, 2008

    I'm completely comfortable with the notion of: put all static content in the Content folder (in various subfolders as desired) and leaving the Views folder as a collection of View templates (at least *now* I'm comfortable with it - now that I've read the other comments above and moved all my content into Content).

  18. Avatar for Jahedur Rahman
    Jahedur Rahman August 10th, 2008

    Hi, I want to allow http access to a swf file. How can I do that in ASP.Net MVC.

  19. Avatar for Michael Velasquez
    Michael Velasquez August 14th, 2008

    Hi, I have a question regarding blocking access to specific directories within the views directory.
    Is there a way, other than specifying the role per action, to block access to specified directories under the views directory, based on role?
    For instance, a web.config with the "BlockViewHandler" key copied into each directory that you'd like access blocked to?
    Rather than blocking the entire views directory.

  20. Avatar for haacked
    haacked August 15th, 2008

    Yeah, you could copy our Web.config file we place within the Views directory and move it to the specific directories you want to block. You'll also have to specify which roles can have access. Lookup information on the <location> element of web.config.

  21. Avatar for demisx
    demisx May 28th, 2015

    Nice article. We can't block everything inside an MVC project because we use feature based organization where are views, controllers, models, CSS, Javascript etc. may live in one feature folder, e.g. 'Dashboard/' or 'Profile/'.