Prevent direct access to files on IIS server - asp.net-mvc

I have two servers, one for my mvc application and the other one as a storage for large files like images etc, both running on Windows Server 2012 R2.
How can I prevent direct access to the files on storage server?
say, mvc is on IP1/ and storage is on IP2/.
Link to a file would be like: IP2/MediaFiles/2015/12/image0001.jpg.
I need only GET requests from IP1 have access to the link above. How?
UPDATE
server1 on IP1 needs to be free of file sharing since media server is on IP2 and we don't need to load files per request on server1's RAM. (server1 will crash soon!) therefore no HttpHandler can be used!
In this question I'm looking for a way to prevent unauthorized users from accessing files on server2 (on IP2) by entering direct address.

Alright I found the solution!
Working on such problems needs some trick gathered from different sources based on your needs. I was looking for a way to prevent unauthorized users from accessing files on file server which is different from your main server. (the main server is authorizing users)
First of all, I blocked ALL incoming requests containing the Url pattern of my sensitive files using IIS rules. Then I wrote some lines of code for file server to handle Http requests using IHttpHandler interface in order to 1) check authorization rules and 2) send exact files to clients without converting them to byte array. And lastly, I used This Link to prettify links to file server! That's all folks ;)
Now:
physical link [blocked] : IP2/MediaFiles/2015/12/image0001.jpg
virtual link : IP2/Please/Find/A/File/By/DB/Id/1 ---> image0001.jpg

All what you wanted is in Web.Config file. You should place it in the root directory of your file storage server if you using IIS there.
In <system.webServer> node you should place this code:
<security>
<ipSecurity allowUnlisted="false"> <!-- this line blocks everybody, except those listed below -->
<clear/> <!-- removes all upstream restrictions -->
<add ipAddress="127.0.0.1" allowed="true"/> <!-- allow requests from the local machine -->
<add ipAddress="IP1" allowed="true"/> <!-- allow the specific IP of IP1 -->
</ipSecurity>
</security>
This rule will be accepted for all subfolders of root folder. If you need to block requests only for specific folder you should place your Web.Config there.

Related

Kentico Library media file not available in MVC website

I'm creating a Kentico media library file using Kentico API 11.0.26. The CMS and MVC app are on a web farm. Both are in healthy state.
The file gets created fine, but is only accessible on the CMS application, not on the MVC website. This is true for both Direct Path link as well we Permanent link.
Copying/pasting the Permanent link in browser preceded with MVC domain gives this message: "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable."
Can someone explain what "same UNC root defined " means in this section:
If you are running the system on a web farm and have the same
UNC root defined on all servers, it is necessary to add the
following key into your web.config file. The files stored in the
libraries are then not transferred when synchronizing the web farm
content:
<add key="CMSWebFarmSynchronizeMediaFiles" value="false"/>
https://docs.kentico.com/k12/configuring-kentico/configuring-the-environment-for-content-editors/configuring-media-libraries
The UNC (Universal naming convention) is the standard for identifying a server/machine on a network, used like so: \\server-name\rest of path
In Kentico, you would be using UNC to tell Kentico where you're storing media library files if it's on a different server in the network.
The first thing that came to mind why you're getting a 404 is it's probably that the media URL has a tilde (~) preceding it. If that's the case, remove that tilde and see if the problem is resolved. Personally, I do a replace like so:
MediaLibraryHelper.GetPermanentUrl(mediaLibraryFile).Replace("~/", "/")
I'm not aware if there's a helper function to give you a URL without string replacing the tilde.

MVC bundles and IIS virtual directories (URL rewrite)

I'm hosting multiple applications on IIS server virtual directories and I'm using URL Rewrite to facilitate them. All images and other assets that are manually written like this "~/path/to/my/content" has a correct output "/path/to/my/content", but bundle paths like "~/client/js" gives an output "/myapplication/client/js" which should be "/client/js".
How can I fix that?
How I initiate Script bundle:
var scriptBundle = new ScriptBundle("~/client/js");
Rewrite configuration:
<rule name="Official Website" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" matchType="Pattern" pattern="^(www\.)?domain\.com$" ignoreCase="true" negate="false" />
</conditions>
<action type="Rewrite" url="officialsite/{R:1}" />
</rule>
Was looking into these topics, but couldn't make anything work for me:
How do I get System.Web.Optimization bundles to work with custom folders in an IIS virtual directory?
CssRewriteUrlTransform with or without virtual directory
Why does ResolveBundleUrl not work for custom folders? (MVC Beta 4)
Is it possible to unit test BundleConfig in MVC4?
UPDATE: I'm using Winhost as hosting provider, and they do not support setting up host headers for the IP, probably due to the shared IP. They provide domain pointers to root folders, which is why I'm using URL rewrite.
You said :
I'm hosting multiple applications on IIS server virtual directories
and I'm using URL Rewrite to facilitate them
So, The problem refers to root configuration (Virtual Directory) to be usable for bundling and etc.., It's not about bundling configuration or rewrite rule. I think you need to setup myapplication directory as virtual and set it up as a separate website. Make sure you have followed instructions available in Create Web Site where it says:
you add a Web site in IIS, a site entry is created in the
ApplicationHost.config file. The entry specifies:
network binding for the site
Maps the site to a location in the file system
optionally specifies user credentials for content access
To ensure that user requests reach the correct Web site, you must configure a unique identity for each site on the server.Web sites hosted on the same server can be distinguished using the following unique identifiers.
Host header name (recommended)
IP address
TCP port number
Configure a Host Header for a Web Site (IIS 7) points to the first one.
Update: I think there may be a name conflict on server and your project. more brightly try to change client in ~/client/js and its folder to new one. Unless there were multiple path choices (with this path depth) for server to fetch that you can solve it by adding an extra depth by adding an \ in your project and js bundle mapping.
Update2: Finally I suggest you to follow full article available in How to publish or host subdomain on winhost.com? to solve such this amazing issue :)
I have two options you can try.
1) Try using this to trick it into using the correct path:
var scriptBundle = new ScriptBundle("~/../client/js");
You may get an HttpException (Cannot use a leading .. to exit above
the top directory.), but it's worth a shot. I cannot replicate your
environment, so I cannot test.
2) Create your own virtual path provider:
Changing ASP.net application root?

MvcSiteMapProvider - Prevent display/serving sitemap.xml

I have a web app that uses MvcSiteMapProvider, but I don't want it to server /sitemap.xml as every page but the login page requires authentication, so there is no need for the public to see my sitemap.
Is there a way to turn off the the /sitemap.xml file in config? Or a way to do it with RoutesConfig?
As per the documentation, if using internal DI, you can disable the /sitemap.xml endpoint using the MvcSiteMapProvider_EnableSitemapsXml setting.
<appSettings>
<add key="MvcSiteMapProvider_EnableSitemapsXml" value="false"/>
</appSettings>
If using external DI, you need to remove this line from the /App_Start/MvcSiteMapProviderConfig.cs file (or anywhere else it may exist in your application startup code).
// Register the Sitemaps routes for search engines
//XmlSiteMapController.RegisterRoutes(RouteTable.Routes);
FYI - although this setting does what you asked, there really was no problem to begin with. Search engines do not scan web sites for XML sitemap files, they have to be explicitly submitted. According to the sitemap protocol, they can be submitted via HTTP request, via search engine control panel, or by adding the location to the \robots.txt file. But none of these are done without explicit intervention on the part of the webmaster. In all cases, the webmaster chooses the URL that the XML sitemap will be hosted at. Unlike the \robots.txt file, there is no default location for it. We chose the most reasonable logical path \sitemap.xml, but technically it could be anything.

How do I protect a file from direct download?

I have a webshop im developing, and some of the products need to be downloadable files (e-books, images, mp3 etc.). I have the files stored in a subfolder in my project and just a reference to them in my DB.
I dont want anyone with a direct file link to be able to download them, i want to control this myself. The download should only be available through my shop - that is, my customer area where the user can see all the e-products they have purchased.
How do i protect the files on my disk from being downloaded except by my code?
There are several ways to prevent the IIS static file handler from serving out the files to a client.
1) Using section in configuration. You can use the hiddenSegments element to specify sub-segment paths that will not be served. Look at %windir%\system32\inetsrv\config\applicationhost.config for how this section is defined and used to prevent access to bin folder and other directories.
<configuration>
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="subdirectoryName" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
2) If you're looking for a simpler "poor-mans" way of blocking static file handler from serving out files, you can make the files "hidden" (from a file system attribute perspective). The static file handler will not serve out hidden files.
The easy answer: Don't place these files inside your site, place them outside the root of your site.
You can configure IIS to not serve requests to this folder with request filtering:
I'm assuming these paths are not paths you wanted to serve?

Forms auth redirecting css/script includes to the login page with HTTP 302

I have some includes on a login page, a css file and a js file.
<link rel="stylesheet" type="text/css" href="../../ext/resources/css/ext-all.css" />
<script type="text/javascript" src="../../ext/bootstrap.js"></script>
the requests the browser makes for these get the 302 response. Forms Auth is seeing the request as unauthorized and redirecting them to the login page. It doesn't realise that the requests are coming from the login page in the first place.
GET http://localhost:50880/ext/resources/css/ext-all.css HTTP/1.1
HTTP/1.1 302 Found
<html><head><title>Object moved</title></head><body>
<h2>Object moved to here.</h2>
</body></html>
I thought perhaps setting the permissions of the includes folder (ext) to everyone might help.
I had the same problem. Here's how I solved it.
In IIS7, click on your website, then double-click the Authentication button.
Click on Anonymous Authentication, then click the Edit... link on the right hand side.
Make sure the "Application pool identity" checkbox is checked.
My application pool is running under the "Network Service" user (not "ApplicationPoolIdentity"). You can choose the Identity in the Advanced Settings of your application pool in IIS. This user has been given full access to the file system for the website.
You need to exclude the css files and images from getting authenticated as following in the configuration file. Using the location tag you can exclude a single file or a directory.
<location path="<RELATIVE_PATH_OF_YOUR_RESOURCE_FILES>">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
So, here's what I did that entirely solved the issue.
First, I made the change to the web.config like everyone else said to do.
I am using Anonymous Authentication in IIS, and as stated in this issue, I went into IIS > Application Pools > Right-clicked my application pool > Edit > changed the app pool to use the Application Pool Identity.
THEN - I went to the parent folder that contains my site, went into permissions for that folder, and added the server's NETWORK SERVICE account to access the folder. That did it for me. It's because the Application Pool is running under ApplicationPoolIdentity, which is the NETWORK SERVICE account on the local machine.
Hope this helps someone!
The issue I had on this was that I had downloaded a jquery plugin from the internet and copied it into my content directory on the webserver and Windows had all the files under it blocked so that they couldn't be access properly by the webserver. Unblocking the files in Windows solved the issue.
Late answer here, but I wanted to help shed some light on this IISsue. (see what I did?)
First, I want to say that David Conlisk's answer is the sure-fire-nail-it-in-the-head-fix-it-every-time answer. But in case you're like me and have deployed many applications with Forms and Anonymous auth where the Anonymous Auth Identity is set to IUSR and all the sudden I'm seeing this problem now, then listen to how I reproduced the issue and hopefully be spared from the same plight.
My standard practice is to have my web application's AppPoolIdentity run as Network Service. Then I just go to the actual directory on disk that the virtual directory is pointing to -> right click -> Properties -> Security Tab -> Edit -> Add the Network Service User -> Grant read/write permissions.
Then I enable Anonyous Authentication on the directories that I need (js, css, etc.) The app pool identity is IUSR by default.
OK. Now all of the sudden in my dev environment, I start getting 302 forms auth redirects on all my css and js! What happened? I did an SVN switch on my web application to a different branch in source control. Ugh. It completely jacked all of my on disk permissions for every single file. The only way I've ever been able to fix it is to delete the whole web app, and do a fresh checkout and re-apply Network Service read permissions (or apply permissions on every single file... and yes I've tried removing and re-adding the permissions on the parent level folder).
So this time, I decide "hell with it. I'm running my web app as Local System. That will show the disk permissions whose boss. This has worked for me from time to time as a short term workaround." But alas, not today. I swear to you that before my eyes I am looking at two deployments of a forms auth web app with exactly the same configuration and the 302 issue is only reproducing on my dev machine. The only difference is the recent SVN switch on my machine.
As soon as I Log in and get a Forms Auth Cookie, the js and css download just fine.
Bear with me, I've just made a shocking discovery. All of the servers I have this deployed on have read permissions granted to MACHINE_NAME\Users. And my dev machine does not. Once I added that to my dev machine, I was able to download my css.
TLDR;
Moral of the story is you can keep the Anonymous Auth Identity as IUSR, but then you have to grant all users read permissions on your web app on disk.
Since this is a bad idea (for security reasons), I'm going to make it my new practice to adopt David C's answer and make the Anonymous Auth Identity run as the application pool identity.

Resources