Always return a 404 when you decide to return a 403

.htaccess, http, http-status-code-403, security

Solution

To complete one of the better answers here (as mentioned by @WebChemist and @JennyD), a good way to solve this is to return `404 Not Found` from the document you use to handle `403` errors. Personally I do something like the following:

`.htaccess` in web root (relevant excerpt):

ErrorDocument 400 /http-errors.php
ErrorDocument 403 /http-errors.php
ErrorDocument 404 /http-errors.php

`http-errors.php` in web root (condensed working example):

<?php

$status = $_SERVER['REDIRECT_STATUS'];
// If it's a 403, just bump it up to a 404
if ( $status == 403 ) $status++;

$codes = array(
  400 => array( '400 Bad Request', 'The request cannot be fulfilled due to...' ),
  404 => array( '404 Not Found', 'The resource you requested was not found...' ),
  500 => array( '500 Internal Server Error', 'The request was unsuccessful...' )
);

$title = $codes[$status][0];
$message = $codes[$status][1];

header( $_SERVER['SERVER_PROTOCOL'] . ' ' . $title );
echo "<h1>$title</h1>\n<p>$message</p>";

Problem

There are several questions already posted here about returning a 404 instead of a 403 in special cases (e.g., .ht* files or a certain directory), but I can't figure out how to simply replace all 403 responses ("Okay, it exists, but you still have to find a way in") with 404s ("Sorry, never heard of it"). I'm hoping that there is a simple solution that won't require updating regexes or other bits of the .htaccess to match site changes, just a simple directive: "whenever you decide to return a 403, return a 404 instead" that applies to the whole site, regardless of configuration changes. Then, if the top level .htaccess contains "Options -Indexes", and any given directory contains no index.html (or equiv), the bare directory URL will return 404, but if I ever add an index.html to that directory, the same bare directory URL will return the index.html, with no updates needed to any .htaccess file. I don't even care if, in the event I ever password a directory, a bad password returns a 404 (because of the 404 -> 403 mapping). In that case, I'm not hiding anything by returning a 404, but it causes no harm either. If there's a way to UNDO the general 403->404 mapping for special cases (rather than DO it for special cases), though, that could be even more useful. Of course, if I'm overlooking something, please set me straight. EDIT: Drat. I was trying to write a good quality question here, but my description of the behavior of "Options -Indexes" in the second paragraph turns out to be wrong. Without that line a bare directory URL shows "index.html" if exists in the directory; otherwise, it reveals the contents of the directory. (That forwarding of /dir to /dir/index.html if index.html exists is the default setup of the Web host, unless I'm mistaken.) Adding the "Options -Indexes" line stops it airing my laundry in public (returning a 403, not 404, but still better than exposing the dir contents), but now the bare directory URL returns a 403 even if index.html exists. I wish a bare dir URL "mysite.com/mydir" displayed /mydir/index.html if it existed and "404" if it didn't, but clearly there's more to it than just replacing the 403s with 404s.

Original source

Related problems