Tom Regan
Tom Regan

Reputation: 3841

Configure IIS to return 404 for directory browse attempts

In IIS (6 or 7), when Directory Browsing is disabled, IIS returns a "403 - Forbidden" error when it detects an attempt to browse a directory (eg "http://mydomain.com/folder").

Is there any way to configure IIS to return a "404 - Not Found" error instead of a "403" for directory browse attempts?

This is an asp.net webforms site.

A security scan of our site noted that returning "403" could assist a malicious person mapping our site; had not thought of that before, but I have to admit it makes sense.

Upvotes: 13

Views: 9906

Answers (5)

Lyle Barbato
Lyle Barbato

Reputation: 31

This is a an old question, but I had to do it in IIS 10 and figured I'd document my solution here since nothing else worked for me and it's basic enough that I suspect it would also work for IIS 6/7.

  1. Disable directory browse.
  2. Changed errors to detailed. (I don't know if this is necessary, but custom didn't work for me.)
  3. I added a custom rewrite rule that essentially looks to see if the request ends in a "/". If it does, I run through my default file list. If any of them are there, I don't rewrite as then the file will render and run correctly. But if none of the defaults are there, then manually direct to your 404 handler. Mine is a custom handler so I rewrite to it, but you can adjust as appropriate.
    <rule name="DirectoryBrowse" enabled="true">
       <match url="(.*)/$" ignoreCase="true" />
       <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
          <add input="{REQUEST_FILENAME}index.whatever" matchType="IsFile" negate="true" ignoreCase="true" />
          <add input="{REQUEST_FILENAME}index.htm" matchType="IsFile" negate="true" ignoreCase="true" />
          <add input="{REQUEST_FILENAME}default.htm" matchType="IsFile" negate="true" ignoreCase="true" />
       </conditions>
       <action type="Rewrite" url="/services/errors/404.whatever?404;https://{HTTP_HOST}{REQUEST_URI}" />
    </rule>
  1. I added this rule last so that my other rewrites/404 redirections, etc., activate before it.

This has an advantage over the other solutions above in that it applies to every directory and there's no need to go into each and add some file and then hide it. shudder

There may be a better way. But it works for me.

Upvotes: 1

Hovhannes Hakobyan
Hovhannes Hakobyan

Reputation: 1326

If you are using ASP.Net MVC add the following handler into web.config

<system.webServer>
  <handlers>
    <add name="StopDirectoryBrowsing" path="*." resourceType="Directory" verb="*" 
         preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
  </handlers>
</system.webServer>

Upvotes: 14

szd
szd

Reputation: 106

The solution that worked for us (IIS7):

  1. disable directory browsing => 403
  2. create a default document (default.htm or whatever default file name is configured) => 200
  3. set the default document's file attributes to hidden => 404

Upvotes: 3

BrianH
BrianH

Reputation: 31

In IIS (7 and above) go to Request Filtering and there is a tab called Hidden Segments. You can just add the name of directory you want to be hidden and it will now return a 404.

Upvotes: 3

Tom Regan
Tom Regan

Reputation: 3841

I could not find a way to configure IIS, but I did find a workaround using an asp.net generic handler (http://forums.asp.net/p/1478217/3453189.aspx, scroll down to the answer by gvlahakis).

First, create a generic handler that returns 404:

public class DirectoryBrowsingAttempt : IHttpHandler
{
    public bool IsReusable {get {return true;}
    public void ProcessRequest(HttpContext context) {context.Response.StatusCode = 404;}
}

Second, add tags to the web.config to point directory browsing attempts to the above handler, one for each folder that you need to protect, in both the httpHandlers and system.webServer sections. The tags below protect a folder named "js" off of the root.

<httpHandlers>
  <add verb="*" path="js/*" validate="false" type="MyNameSpace.DirectoryBrowsingAttempt"/>
</httpHandlers>
<system.webServer>
<handlers>
  <add name="NoAccess" verb="*" path="js/*"  preCondition="integratedMode" type="MyNameSpace.DirectoryBrowsingAttempt"/>
</handlers>

This workaround behaves differently in IIS 6 vs. IIS 7. For example, I protected a folder that contained the site's images in this manner: IIS 6 still delivered the images contained in this folder to web pages (the desired behavior, I just want to block directory browsing attempts); IIS 7 blocked them.

There are probably ways to use the "location" tab in the web.config to allow images to be served up by overriding the default image handler, but I've no desire to go that far down the rabbit hole.

Upvotes: 1

Related Questions