Only allow localhost to certain page on asp.net - asp.net

I have a page that generates a PDF and then returns it to the user. The functionality to generate the PDF will hit other ASP.NET pages and then render those pages as a PDF.
What I want is to only allow those ASP.NET pages to be accessed locally (by the PDF generator). Therefore blocking direct access will allow only the PDF processing tool to get access to it since it is running locally within the ASP.NET application.
I tried adding an ipSecurity element in the web.config to only allow localhost to get access to those aspx pages. Running all of it locally on my machine while developing works fine, however when I deploy and try to generate a report I get a 403 error.
The page that I am requesting that generates the report is in FolderNameHere/ReportPage.aspx. The function on this page will then call the pages in FolderHere/Code/Report to generate the PDF. The problem is I think when I access `FolderNameHere/ReportPage.aspx, it is passing my IP address to future accesses to the Report folder pages even though the function is running locally. Is there a way I can block direct access to these pages except from locally running functions that are called by non local addresses. Here is my config that unfortunately isn't doing the trick.
<location path="Requisite/Code/Report"> <!-- TODO: Move to WebConfig in Requisite-->
<system.webServer>
<security>
<authentication>
<anonymousAuthentication enabled="true"/>
</authentication>
<ipSecurity allowUnlisted="false">
<clear />
<add ipAddress="127.0.0.1" allowed="true"/> <!-- only allow local host -->
</ipSecurity>
</security>
</system.webServer>
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>

There's often a distinction between the loopback IP address and localhost. Try changing 127.0.0.1 to localhost on the deployed config.

Related

Url Authorization with MVC and ASP.NET Identity

I want to secure specific folders and resources in my application that are outside of the routes for my mvc application. I want these resources to only be available to authenticated users (which role is not of concequence as long as they are authenticated).
Initially it seemed that the UrlAuthorizationModule would be the answer. I followed this article, Understanding IIS 7.0 URL Authorization, and I can get the module to work in the sense that it responds to the configuration elements in the web.config.
My current problem is that I think it is enacting the rules based on the anonymous user in IIS and not the authenticated user in asp.net identity.
Test Environment
I use a standard html file for testing instead of trying to load a script as this would also be loaded outside of the MVC pipeline.
In Visual Studio 2015.
New default .net 4.6.2 web project
MVC template
Authentication = Individual User Accounts
IIS 8 (for testing outside Visual Studio)
Authentication -> Anonymous Authentication (enabled)
Add to web.config
<configuration>
...
<location path="Data">
<system.webServer>
<security>
<authorization>
<clear/>
<add accessType="Deny" users="*"/>
<add accessType="Allow" users="?"/>
</authorization>
</security>
</system.webServer>
</location>
...
</configuration>
Add to folder structure
/Data/Protected.html // this file just has some basic Hello World content to display so you can see if it is loaded or not.
Observed Results
With this configuration everything in the Data path is always denied, it does not matter if the user is authenticated or not.
The same is true if I switch the 2 lines for Deny and Allow in the web.config.
If I completely remove the line with Deny then access is always allowed even when the user is not authenticated.
If I add a role and use roles with the role name instead of users attribute the role is also completely ignored.
Now What?
What am I missing? How can I get the Url Authorization module to work with MVC/WebAPI and ASP.NET Identity Individual user accounts or is this simply not doable?
I am open to alternative ideas as well, maybe the answer is to write a custom HttpModule or HttpHandler?
Side notes
Why & Specifics
These resources are javascript files, in short only a portion of the scripts should be available to unauthenticated users. There are 2 directories in the root, one for the authenticated part of the app and one for the non-authenticated part of the app. The reason for this has nothing to do with user authorization or security in the application, it is to limit the exposed surface area of the application to non-authenticated requests.
[TL;DR;]
Go to "Complete root web.config" section to see the needed web.config setup.
Test this in incognito-mode to prevent browser caching issues!
And use Ctrl+F5 because scripts and html files get cached.
First deny access to all anonymous users in the root web.config.
<authorization>
<deny users="?"/>
</authorization>
The web.config here allows one folder to be publicly accessible. This folder, in my example here, is called css and sits in the root of the MVC application. For the css folder I add the following authorization to the root web.config:
<location path="css">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
You can add more of these location paths if you want more public folders.
While all other files will not be accessible until the user logs in, the css folder and its contents will always be accessible.
I have also added a static file handler to the root web.config, This is critical as you want the request to be managed by the asp.net pipeline for the specific file type(s):
<handlers>
<add name="HtmlScriptHandler" path="*.html" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />
</handlers>
Complete root web.config
<system.web>
<authentication mode="None" />
<authorization>
<deny users="?"/>
</authorization>
<compilation debug="true" targetFramework="4.6.2" />
<httpRuntime targetFramework="4.6.2" />
</system.web>
<location path="css">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</modules>
<handlers>
<add name="HtmlScriptHandler" path="*.html" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />
</handlers>
</system.webServer>
ASP.NET by default will only apply the allow and deny rules to files handled by the managed handler. Static files are not managed by the managed handler.
You could also set: (Don't do this, if not really needed!)
<modules runAllManagedModulesForAllRequests="true">
With runAllManagedModulesForAllRequests="true" all the HTTP modules will run on every request, not just managed requests (e.g. .aspx, ashx). This means modules will run on every .jpg ,.gif ,.css ,.html, .pdf, ... request.
One important thing
You don't have to add the UrlAuthorizationModule to the modules section as it is already part of the ASP.NET pipeline. This means, it will run only for managed files, not static!
If you now remove and then re-add the UrlAuthorizationModule to the modules section, it will run under precondition "integratedMode" and not under "managedHandler" anymore! And will therefore have access to static files.
<remove name="UrlAuthorization" />
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
If you set the precondition to managed:
<add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" preCondition="managedHandler" />, then the UrlAuthorizationModule will not restrict access to static files anymore.
You can test this by accessing a script file in the scripts folder successfully while being logged out. Hit Ctrl+F5 to make sure you get a fresh copy of the script file.
Difference between ASP.NET UrlAuthorization <--> IIS URL Authorization
It is important to keep in mind that the managedHandler precondition
is on the ASP.NET UrlAuthorization module. The precondition tells you
that the URL authorization module is invoked only when the code that
handles the request is mapped to managed code, typically an .aspx or
.asmx page. IIS URL Authorization, on the other hand, applies to all
content. You can remove the managedHandler precondition from the
ASP.NET Url Authorization module. It is there to prevent a performance
penality you have to pay when every request (such as a request to
.html or .jpg pages) would have to go through managed code.
P.S.: Some web.config attributes are case sensitive!

Access my own site via curl directly from webserver, but disallow access from outside

I want to use cURL from my webserver to call a page on my website (importdata.aspx) on that same webserver. But I want to make sure the importdata.aspx page can not be accessed from the internet.
I use forms authentication on my site, so I can't have the cURL call login for me.
In my web.config file I've disallowed non-authenticated users:
Setting up a different site and allowing anonymous users through IIS, still won't let me access importdata.aspx, as my formsauthentication would prevent that right?
Is there a way to allow importdata.aspx to be accessed only through the local machine and blocking it completely from outside?
Web.config files have some options to set different configs, based on the URL path. https://msdn.microsoft.com/en-us/library/ms178692(v=vs.90).aspx
Example:
<configuration>
<system.web>
<sessionState cookieless="true" timeout="10" />
</system.web>
<!-- Special configuration for the "importdata.aspx" -->
<location path="importData.aspx">
<system.web>
<authentication mode="Windows" />
</system.web>
</location>
</configuration>
In this example, I defined a different authentication mode for the importData.aspx file.

Web.config: Allow all users on given path at machine level

I have successfully setup Elmah at machine level in order to have error logging for all web applications. Now I want to add the RSS feed of each application to Outlook. Problem is applications are secured and won't allow Outlook to access RSS feed (at my.web.application.com/elmah.axd/rss). Since I can't ask Outlook to login in the app, I figured I'd give access to anybody to the elmah path and restrict by IP address (actually restricting to our local network), with the following config:
<location path="elmah.axd">
<system.web>
<authorization>
<allow users="*" />
</authorization>
</system.web>
<system.webServer>
<security>
<ipSecurity allowUnlisted="false">
<clear/>
<add ipAddress="127.0.0.1" allowed="true" />
<add ipAddress="10.0.0.0" allowed="true" subnetMask="255.255.255.0" />
</ipSecurity>
</security>
</system.webServer>
</location>
This actually works when put in the application's Web.config: I have access to the elmah.axd page without logging in. Perfect. Now I wanted to do this at machine level so every application behaves the same. So I put it at the same places I put the Elmah config, that is:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\web.config
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG\web.config
C:\Windows\System32\inetsrv\config\applicationHost.config (IIS config)
Although putting the config there made Elmah respond on every web application, it doesn't work with that security config: the applications still ask to login... What need I do to make it work at machine level ?
Would it be that in machine level web.config the path is not relative to the applications ? but then how can I make it work ? (I also tried ~/elmah.axd without success...)
Check for overrides in each application's configuration.
The local configuration settings override settings in parent
configuration files.
Source: https://msdn.microsoft.com/en-us/library/ms178685%28v=vs.140%29.aspx

How to Prevent direct access to files and folders in asp.net?

I have deployed a web application on IIS7 and the application has mail attachment files saved on webserver's Attachments folder and it's working fine when the attachment is downloaded from
application.
The problem is when the same url viewed from Chrome is typed from a different machine the same can be viewed/downloaded. I tried couple of solution after googling but here the Attachments folder on webserver have security enabled for Network services.
http://machine-121/AdminManagement/Attachments/58501/17112014131251/FilledForm.pdf (can be read)
I tried
<configuration>
<system.web>
<authentication mode="Forms"/>
<authorization>
<deny users="?"/> <!--This will restrict anonymous user access-->
</authorization>
</system.web>
<location path="login.aspx"> <!-- Path of your Registration.aspx page -->
<system.web>
<authorization>
<allow users="*"/> <!-- This will allow users to access to everyone to Registeration.aspx-->
</authorization>
</system.web>
</location>
</configuration>
but couldn't succeed any suggestion/help would be of great help.
The problem is that the .pdf extension isn't caught by the ASP.NET handlers, since that isn't a file type that is mapped to ASPNET_ISAPI (aka the ASP.NET HTTP Runtime). Hence the filtering in your web.config file doesn't apply to those files.
You have two options:
Map all file extensions (or at least pdf files in this case) to ASPNET_ISAPI using the IIS configuration panel. Note that this will increase the load on your server since the overhead of IIS on itself is lower than IIS + ASP.NET;
Use an HTTP handler that gets the file for you. This allows you to do some fine grained authorization checks on the file access too. See the Introduction to HTTP Handlers.
The best solution for this problem is the create a HTTP Handler in which you can restrict download files based on certain conditions. check this link for more information
I think the easiest thing to do is add the runAllManagedModulesForAllRequests attribute to your modules section in web.config, like so:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Managed to block XML direct access in IIS and still allowing the app to query the file with the following rule:
<rule name="Prevent XML direct access" enabled="true" stopProcessing="true">
<match url=".*filename\.xml$" />
<conditions>
<add input="{QUERY_STRING}" pattern="^part_of_query.*$" negate="true" />
</conditions>
<action type="Redirect" url="/error" appendQueryString="false" />

Redirecting Windows Authentication to a custom 401 page

We are converting some of our web applications that used to run under forms authentication, to now run as windows authentication. I want to recreate the page security that forms authentication had with minimum modification to the actual pages. I was able to recreate the effect I want, with a simplified web app. I am running the app on Server 2008 R2 integrated pipeline IIS 7.5.
I created a simple 3 page app using windows authentication. The three pages are:
Openpage.aspx, that is open to any authenticated user
Blockedpage.aspx that is blocked to all users (symbolic of a directory or page that would be blocked to a subset of users based on user role)
ErrorPage.aspx,if blockedpage.aspx is accessed (and rejected) the application should forward to ErrorPage.aspx where the user gets generic information about the application.
The Web.Config for the app:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows"/>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
</system.web>
<location path="blockedpage.aspx">
<system.web>
<authorization>
<deny users="*"/>
</authorization>
</system.web>
</location>
<system.webServer>
<httpErrors errorMode="Custom" >
<remove statusCode="401" subStatusCode="-1" />
<error statusCode="401" path="/development/simplesecurityapp/errorpage.aspx" responseMode="ExecuteURL" />
</httpErrors>
<validation validateIntegratedModeConfiguration="false" />
<defaultDocument>
<files>
<clear />
<add value="openpage.aspx" />
</files>
</defaultDocument>
</system.webServer>
</configuration>
(If I don’t attempt to redirect the 401 errors at the asp.net level, I just get the standard “not authorized message” which is not the effect I want to give my users.)
However, I am getting an error that I don’t understand – every time the server resets, the app stops working. IIS simply returns 401 errors until the browser pops up a manual log-in control, which cannot be satisfied. (I never want my users to be presented with the browser log-in prompt)
However, if I replace the httperrors section once the application is set up (either by editing the web config, or updating it with the server GUI) removing the section, accessing the page, and then adding the section back, the application starts to work as expected, and continues to until the server is rebooted, at which time it starts giving users the manual login pop-up again, which they cannot resolve.
1) Is this the correct way to secure an app with windows authentication (is there a better way to configure a directory inaccessible like in forms, yet still supply a custom error page?)
2) Is this an effect of the integrated pipeline and why is it working this way?
You're trying to provide content over a transport error message.
Forms allows you to do this because it's composed of layer 7 stuff, like 302s and 200s. 401s are interpreted by the client browser as "the server didn't like my credentials, so raise a dialog box to ask for new ones".
An authenticated page produces at least 1 401 in order to become authenticated; that you're overloading the "error" for something else is probably the root of the problem.
I'm not sure there's an elegant way of doing what you want.

Resources