What is forbidden.html that requests get redirected to for 403 errors?

Say, I have a folder on my site configured for 0700 permissions, which makes all outside requests to generate 403 access denied… or so I thought. When I tried going to a file in that folder in a web browser, I got redirected to: https://mywebsite.com/forbidden.html that instead generated error 404. Hmmm?

What is this forbidden.html and how can I configure it to redirect to a PHP script instead?

Dreamhost’s Apache servers have pre-configured setting for the ErrorDocument directive. Something like:

ErrorDocument 404 /missing.html
ErrorDocument 403 /forbidden.html
...

The reason for this is to make it easy to add custom error pages. For example, a custom 404 page can be added by just creating the /missing.html file. If the custom error files aren’t found, the User-Agent (browser) still sees the correct error code.

Unfortunately these directives can interfere with more advanced sites, where you might want to handle the errors yourself. You can suppress the error-document settings by reseting them to default in the site’s .htaccess file. I often use the following, to “reset” ErrorDocument:

# Suppress DH's custom error docs
ErrorDocument 401 default
ErrorDocument 403 default
ErrorDocument 404 default
ErrorDocument 500 default

Hmm, is there some caching involved there? I don’t see any difference. Before I had these lines in my root .htaccess:

# Error pages:
ErrorDocument 401 /err401.php
ErrorDocument 403 /err403.php
ErrorDocument 404 /err404.php
ErrorDocument 500 /err500.php

That I changed to this after reading your comment:

# Suppress DreamHost's custom error docs
ErrorDocument 401 default
ErrorDocument 403 default
ErrorDocument 404 default
ErrorDocument 500 default

# Error pages:
ErrorDocument 401 /err401.php
ErrorDocument 403 /err403.php
ErrorDocument 404 /err404.php
ErrorDocument 500 /err500.php

But it still didn’t do anything.

Ah, interesting. If you set 0700 permissions on a directory, then that prevents all .htaccess processing. The result is that the requests are handled based on Apache-DH’s default setup (i.e. uses /forbidden.html for 403 errors, etc).

For example, if the directory example.com/foo/ has 0700 perms, then, you’ll see errors like this in error.log:

[core:crit] [pid ...] (13)Permission denied: [client ...] AH00529:
   /home/user/example.com/foo/.htaccess pcfg_openfile: unable to check htaccess file,
   ensure it is readable and that '/home/user/example.com/foo/' is executable

If the directory is readable, but a file has 0700 perms, then .htaccess rules apply normally. For example, if example.com/bar.html has 0700 perms, then you’ll see a normal permission-denied error:

[core:error] [pid ...] (13)Permission denied: [client ...] AH00132:
  file permissions deny server access: /home/user/example.com/bar.html

So this suggests one work-around is to make the directory readable, but keep its files with 0700 perms. Assuming auto-indexing is turned off (Options -Indexes), then all 403 errors should be handled by a custom ErrorDocument directive.

Another work-around might be to just use the default /forbidden.html, but force it to run PHP. For example, using the FileMatch directive:

<FilesMatch "^forbidden\.html$">
   SetHandler php-cgi
</FilesMatch>

There are probably lots of other variations. Also, if possible, consider moving the 0700 files outside of the site’s web directory – ideally, for security, there shouldn’t be anything in web directory that isn’t meant to be served.

Yeah, I know. Thank you. The website is already coded that way. I guess I can adjust the website for the hosting provider’s quirks, or do it the other way around. I’ll prefer the latter.

Thanks for suggestions though. But …

Your first suggestion is not very feasible because I will be regularly adding and removing files in that “forbidden” directory. So it is VERY easy to forget to set permissions on a new file.

The second suggestion would work … but is also quite dangerous. I’ve burnt on it with shared hosts before. You set up some file (that is not treated as PHP by default) to be treated as PHP script, and it works … until the hosting provider in its infinite wisdom decides to muck around with your .htaccess file without your knowledge (to install an update or some other “latest and greatest” feature) and as a result all of sudden your PHP script starts being served as HTML. Yep… been there, done that.

So do you know, is there any way to configure that default setting on my account to at least redirect to /forbidden.php?

Another mechanism would be to rewrite the /forbidden.html request that is generate by the default ErrorDocument setup. For example:

RewriteRule ^forbidden.html$ /err403.php

That works in a simple test rig, but you’ll have to watch out for interacts if you have other rewrite rules. The above rule should probably be placed before other more-general catch-all rewrites that might report a 404 for /forbidden.html (as you mention in your first post).

Thanks, man. Thanks for sticking out with me on this one.

I did try the RewriteRule like you suggested even before I posted my previous answer. The problem with redirecting forbidden.html to my /err403.php is that it loses the original request-URI. The whole point of processing it via PHP is that I can log $_SERVER['REQUEST_URI'] in the database. That’s a very handy way of seeing if there are any SQL-Injection or other brute-force attacks ongoing on your website. On the other hand, it also shows if you forgot to “open up” some auxiliary files that modern apps and browsers use these days.

Unfortunately with this redirect:
RewriteRule ^forbidden.html$ /err403.php

the request URI becomes /forbidden.html

The same is true by the way with:

<FilesMatch "^forbidden\.html$">
   SetHandler php-cgi
</FilesMatch>

It just butchers $_SERVER['REQUEST_URI'] to /forbidden.html even if I run it as PHP :frowning:

In my simple rewrite-rule test rig, I see the following variable set in 403.php:

Variable Value
$_SERVER[‘SCRIPT_NAME’] /403.php
$_SERVER[‘REQUEST_URI’] /foo/
$_SERVER[‘REDIRECT_URL’] /forbidden.html

Apache cyclically applied rewrite rules, so possibly you have other rules being applied. You may need to “short-circuit” the cycle with the last flag:

RewriteRule ^forbidden.html$ /err403.php [last]
#### Yet another alternative:

Does the “forbidden” directory have a fixed name/location? If so, then another option is to use a simple Redirect directive to send all requests to a custom 403 page. For example, if the “forbidden” directory is /nogo, then the following will send all requests (/nogo, /nogo/foo, etc) to 403.php:

ErrorDocument 403 /403.php
Redirect 403 /nogo

With this style of redirect, Apache doesn’t even try to access the nogo directory, so it doesn’t matter what its permissions are, or even whether it exists. This sort-of gives you an extra layer of security, since access will be restricted is two ways: by .htaccess rule, and by directory permissions. Either can fail (deleted .htaccess or bad perms) and the files will still be protected.

Oops, my last suggestion about Redirect is incorrect – Apache still tries to access the nogo directory…

Another option that is similar to the failed Redirect idea above is to give Apache permission to read /nogo, but include an .htaccess file to deny access. For example, /nogo/.htaccess:

Require all denied

Like the directory permissions, this would just be a single layer of security – if the nogo/.htaccess file was accidentally deleted, the nogo files would be visible. Another layers could be added by including a Redirect 403 /nogo in the root .htaccess file.

Hmm… thanks. I’ll have to check this out.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.