ASP.NET MVC 5 Identity & Securing Folders - asp.net

Well, I'm at a loss. I've looked everywhere and I'm still getting errors. I have a folder with a couple of pdf files stored in it. The folder is called "docs" and it's in the root directory of my project. I placed a web.config file in the folder with the following code...
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
I also tried placing the code in my root web.config file using the following code...
<location path="/docs">
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</location>
Both of these code blocks produce a 500 server error. Unfortunately, I don't have access to the detailed server error since I'm on shared hosting. Any ideas?
Edit: Sorry... That's what I get for posting a question a 1am. I want to secure the folder so that only those users who are logged in and authorized can access it and download files.

I had a similar problem (see here). The solution was to add the web.config to the directory but also to add a handler directive to it. This worked for me.
<?xml version="1.0"?>
<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
<system.webServer>
<handlers>
<add name="PDFHandler" verb="*"
path="*.pdf"
type="System.Web.StaticFileHandler"
resourceType="Unspecified" />
</handlers>
</system.webServer>
</configuration>

I want to secure the folder so that only those users who are logged
in and authorized can access it and download files.
If you just want to restrict downloads to logged-in and authenticated users, then GlenBee’s solution is by far the simplest and most effective one.
If you need to restrict access by role and/or claim, you have two choices:
If you are comfortable with security by obscurity, you can control access to the page that has the links to the files. The files are stored within the wwwroot, so that all you need to do is link to them on a page that does the role/claim filtering. The downside is that anyone can guess the file paths and names, and gain access to them without having the correct role/claim (although you should still secure the file directory for only authenticated users as per GlenBee’s solution).
If you need to ensure that, without exception, no-one can access the files except those people authorized to do so by virtue of their role/claim (or some other requirement, such as direct ownership), you will have to protect not just the page with the links (filtering for role/claim/ownership), but also create a file handler that passes the files off to the user to be downloaded (filestream, etc.), and to have the files themselves stored outside of wwwroot so they cannot be accessible via plain HTTP. This ‘file hand-off script’ ensures that the user being handed the file actually has the role/claim/ownership required, instead of just being able to blindly guess the path to the file; and storing the file outside of wwwroot ensures that only the script can grab the file in the first place.

I am doing the same thing, here is the contents of the web.config that I placed in the folder:
<configuration>
<system.web>
<authorization>
<deny users="?" />
</authorization>
</system.web>
</configuration>
And with the errors:
A simple solution I do is turn on health monitoring and have it email me errors, this is in my root web.config:
<system.web>
<healthMonitoring enabled="true">
<eventMappings>
<clear/>
<!-- Log ALL error events -->
<add name="All Errors" type="System.Web.Management.WebBaseErrorEvent, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" startEventCode="0" endEventCode="2147483647"/>
<!-- Log application startup/shutdown events -->
<!--<add name="Application Events" type="System.Web.Management.WebApplicationLifetimeEvent" startEventCode="0" endEventCode="2147483647"/>-->
</eventMappings>
<providers>
<clear/>
<!-- Provide any customized SqlWebEventProvider information here (such as a different connection string name value -->
<add name="SqlWebEventProvider" connectionStringName="ConnectionString" maxEventDetailsLength="1073741823" buffer="false" type="System.Web.Management.SqlWebEventProvider"/>
<add name="EmailWebEventProvider" buffer="false" type="System.Web.Management.SimpleMailWebEventProvider" from="website#example.com" to="webmaster#example.com" subjectPrefix="Website Error: "/>
</providers>
<rules>
<clear/>
<add name="All Errors Default" eventName="All Errors" provider="SqlWebEventProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:00:00"/>
<!--<add name="Application Events Default" eventName="Application Events" provider="SqlWebEventProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:00:00"/>-->
<add name="All Errors To E-Mail" eventName="All Errors" provider="EmailWebEventProvider" profile="Default" minInstances="1" maxLimit="Infinite" minInterval="00:00:00"/>
</rules>
</healthMonitoring>
</system.web>
<system.net>
<mailSettings>
<smtp from="no_reply#example.com">
<network host="mail.example.com" userName="website#example.com" password="P#$$w0rd"/>
</smtp>
</mailSettings>
</system.net>

Related

How do I prevent unauthenticated access to .csv file in sub folder using forms authentication

I have an ASP.NET application that uses forms authentication and allows users to have some non-ASP.NET files like .txt or .csv created in a subfolder for download. While access to the subfolder for browsing is correctly blocked if the user is not signed in, viewing/downloading .txt or .csv files is possible without being signed in. How do I ensure that only logged in user are able to download any files from that subfolder (without additional login)?
My last try was this (found in some other posting) in web.config, to try to force ASP.NET to also handle .csv and .txt files and include them in its forms authentication:
<system.webServer>
<modules>
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</modules>
...
If I remember correctly, this should do the trick:
<location path="Folder/">
<system.web>
<authorization>
<allow roles="YOURROLE" />
<deny users="*"/>
</authorization>
</system.web>
</location>
In order for this to work I think application must be running in integrated mode or at least introduce the file types in mime settings.
This in the main web.config finally did it for me, without the need for any other changes. It forces all file types to be processed by ASP.NET, including CSV files, so all files are now protected by forms authentication. I just hope though that this does not have any unwanted side effects, as this solution is more global than what I hoped for, not just to protect one specific file type in one subfolder. Comments welcome.
<system.webServer>
<modules>
<remove name="FormsAuthenticationModule" />
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
</system.webServer>
Source: https://learn.microsoft.com/en-us/iis/application-frameworks/building-and-running-aspnet-applications/how-to-take-advantage-of-the-iis-integrated-pipeline

Deny all files in a directory, via web.config setting

As a test, I'm trying to use the web.config to control security in the following ways:
Deny access to all files in a directory, except for a specific file
Allow access to all files in a directory, except for a specific file
So I set up the web.config as follows:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- Deny access to all files in a directory, except for a specific file -->
<location path="NonAccessibleDirectory">
<system.web>
<authorization>
<deny users="?"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<location path="NonAccessibleDirectory/AccessibleFile.html">
<system.web>
<authorization>
<allow users="?"/>
<allow users="*"/>
</authorization>
</system.web>
</location>
<!-- Allow access to all files in a directory, except for a specific file -->
<location path="AccessibleDirectory/NonAccessibleFile.html">
<system.web>
<authorization>
<deny users="?"/>
<deny users="*"/>
</authorization>
</system.web>
</location>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
</configuration>
As expected:
If I browse to the non accessible directory and do not specify a file, I get access denied
If I browse to the accessible directory and do not specify a file, I can see the list of files
The problems I'm having are:
If I browse to the non accessible directory and specify a file, I can view it, and I would have expected not to be granted access
If I browse to the accessible directory and specify a file I have denied access to via the web.config, I can still view it, and I would have expected not to be granted access
Amy I configuring things wrong?
You may be running in to the difference between ASP.NET URL Authorization and IIS URL Authorization. A detailed summary on this is at http://www.iis.net/learn/manage/configuring-security/understanding-iis-url-authorization#Differences
Briefly, what happens with ASP.NET by default with web.config is that it only apply the allow and deny rules to files handled by the managed handler.
Files such as .txt and .html files are handled by IIS and not ASP.NET, so the authorization rules aren't applied to them.
You can test this out by adding this to your main web.config to use the IIS version.
<system.webServer>
<modules>
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</modules>
</system.webServer>
I tested this with your same security and same directories and files, and all appears to work
A more complete version if you use other authentication methods such as forms could be this
<system.webServer>
<modules>
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
</system.webServer>

Restrict download for general files in Web.Config

I need to restrict client access to some specific files. I would like to do it in my web.config instead of relying on who manages the IIS.
I know it is possible to restrict access to file types (for example, all XML files), as seen here: How to restrict download of specified file types
However, how to specify exact file(s)? For example, I would need to block direct access to the file at ~/test/mytest.xml
Keep in mind that another copy of this file, located at ~/secondtest/mytest.xml should still be available to the client.
The only option is in IIS? I can't control it in the web.config?
Thanks!
You can directly specify the file name like following in web.config.
<system.web>
<httpHandlers>
<add path="test/mytest.xml" verb="*" type="System.Web.HttpForbiddenHandler"/>
</httpHandlers>
</system.web>
For IIS7 onwards use following.
<system.webServer>
<handlers>
<add path="test/mytest.xml" verb="*" type="System.Web.HttpForbiddenHandler" name="XML"/>
</handlers>
</system.webServer>
You can restrict access from logged in, anon, specific roles, etc to paths and/or files in your web.config as such:
<location path="filename or path">
<system.web>
<authorization>
<deny users="*" />
</authorization>
</system.web>
</location>
You might also need to put the following in your config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>

Restrict File Access From URL

I have a site developed in ASP.NET which is hosted.Now in my site there is folder known as "upload" in which some .rar files are saved for private use.When I directly type the url, the file gets downloaded.
Say suppose the file is at "http://www.mathew.com/uploads/mine.rar",if i type the url in the browser and hit enter,it downloads the file even though directory listing is not there.
I want to restrict this..How can I achieve it.
Thanks,
Mathew
You can restrict that by authorization. Put a web.config file in this folder with:
<configuration>
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
EDIT :
This won't work since rar files are not handled by asp.net, so in addition you need to add a handler for asp.net treat rar files like aspx files:
For classic mode:
<system.web>
<httpHandlers>
<add verb="*" path="*.rar" type="System.Web.UI.PageHandlerFactory" />
</httpHandlers>
</system.web>
For integrated mode (default for iis 7.5 and VS 2012)
<system.webServer>
<handlers>
<add name="rar" path="*.rar" verb="*" type="System.Web.UI.PageHandlerFactory"/>
</handlers>
</system.webServer>

How do I protect static files with ASP.NET form authentication on IIS 7.5?

I have a website running on a IIS 7.5 server with ASP.NET 4.0 on a shared host, but in full trust.
The site is a basic "file browser" that allows the visitors to login and have a list of files available to them displayed, and, obviously, download the files. The static files (mostly pdf files) are located in a sub folder on the site called data, e.g. http://example.com/data/...
The site uses ASP.NET form authentication.
My question is: How do I get the ASP.NET engine to handle the requests for the static files in the data folder, so that request for files are authenticated by ASP.NET, and users are not able to deep link to a file and grab files they are not allowed to have?
If you application pool is running in Integrated mode then you can do the following.
Add the following to your top level web.config.
<system.webServer>
<modules>
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
</system.webServer>
Now you can use the standard ASP.NET permissions in your web.config to force forms authentication for all files in the directory.
<system.web>
<authorization>
<deny users="?" />
</authorization>
<authentication mode="Forms" />
</system.web>
I had the same problem with getting roles to authenticate. Through trial and error I finally got it to work with a small edit to #Joel Cunningham's code:
<modules runAllManagedModulesForAllRequests="true" >
I used these two sites as references: http://forums.iis.net/t/1177964.aspx and http://learn.iis.net/page.aspx/244/how-to-take-advantage-of-the-iis-integrated-pipeline/
This is an old thread, but I happened on it and ran into the same problem as Egil. Here is the version of Joel's fix that includes roles:
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthenticationModule" />
<add name="FormsAuthenticationModule" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
<remove name="RoleManager" />
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
Addendum:
As #eych noted the accepted answer also blocks access to the ~/Content folder (or wherever you have your CSS), and ~/Scripts, and so on.
If you want to allow exceptions -- i.e. allow certain files/folders to be accessible by unauthenticated users -- you can do that by means of the location element. Add the following to web.config:
<location path="Content">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
</location>
Update:
An alternative solution is to is to leave access on by default -- which will allow access to your CSS / JavaScript / etc. -- and apply the "lock" (only) to the folder where the static content is stored:
<location path="data">
<system.web>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</location>
Caveat: in our case (an MVC site) we needed to decorate all our controller actions (except login) with [AuthorizeAttribute]. Which is a good idea anyway, but had previously not been necessary (because previously any unauthorized request was redirected to the login page).
I wanted to know why it would be required to re-add modules (with default options) that are added by default for the Integrated Pipeline, so I dug a little deeper.
You need to remove and re-add the modules because, by default, the modules aren't added with the default options. They have a precondition added for backwards compatibility to run only for content handled by a registered ASP.NET handler (e.g., .aspx pages).
The default looks like this:
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"
preCondition="managedHandler" />
By removing the modules and re-adding them without a precondition, those individual modules run for every request (including your static content). It is more granular than enabling runAllManagedModulesForAllRequests.
You can read about it in a couple articles from when the Integrated Pipeline was introduced with IIS 7:
ASP.NET Integration with IIS 7
How to Take Advantage of the IIS 7.0 Integrated Pipeline
Note that there is a typo or the module name in the second article (and #John's answer) was changed from FormsAuthenticationModule to FormsAuthentication at some point.
The set of working modules in IIS 7.5 thru 8.5 looks like this for me:
<system.webServer>
<modules>
<!-- Re-add auth modules (in their original order) to run for all static and dynamic requests -->
<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
<remove name="RoleManager" />
<add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</modules>
</system.webServer>
If you application pool is running in Classic mode, you can do the following. You will have to repeat these steps for each file extension you'd like to handle, but I'm using .html here.
First, add a page build provider to the Web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<compilation>
<buildProviders>
<add type="System.Web.Compilation.PageBuildProvider" extension=".html"/>
</buildProviders>
</compilation>
</system.web>
</configuration>
Then add a page handler factory:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpHandlers>
<add type="System.Web.UI.PageHandlerFactory" path="*.html" verb="*"/>
</httpHandlers>
</system.web>
</configuration>
Then add a page handler:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<add scriptProcessor="C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" path="*.html" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" name="HtmlHandler-Classic-32" />
<add scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness64" path="*.html" verb="GET,HEAD,POST,DEBUG" name="HtmlHandler-Classic-64"/>
</handlers>
</system.webServer>
</configuration>
This worked for me. (Credit: http://www.ifinity.com.au/Blog/EntryId/66/How-To-301-Redirect-htm-or-html-pages-to-DotNetNuke-aspx-pages.)

Resources