2

I have something like this:

Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
Order deny,allow
Deny from all
<FilesMatch "index\.php|api\.html|api_fetch\.js">
  Allow from all
</FilesMatch>
<Directory /blog>
Allow from all
</Directory>
RewriteEngine off

The idea is to limit access in current directory (this one happen to be www-root) to whitelisted stuff and let .htaccess in any other directory, if there is one, do their own stuff. So this way, when I visit www.example.com/blog/, .htaccess generated by WordPress will do its work.

The problem is that .htaccess seems to be applying rules globally so my /blog/ gets the same restrictions.

How can I scope specific .htaccess per dir and let others do their job recursively starting from RewriteBase (i.e. WP's RewriteBase /blog/ should continue recursively everywhere unless specific directory like wp-admin/ as its own .htaccess)?

0

Use mod_rewrite to control access, instead of mod_authz_...

UPDATE: Because in .htaccess you simply don't have the fine grained control you require to limit access to a specific directory using the mod_authz_... directives. You would need access to the server config / VirtualHost. An inherent feature of .htaccess (directory context) is that it applies to the current directory and all subdirectories.

mod_rewrite is a powerful module that gives you the fine grained control you require. Since mod_rewrite is not inherited (by default), any mod_rewrite directives in subdirectories will naturally override directives in the parent - which would seem to be what you require.

Alternatively, you rethink your current directory structure and move the files that you want to protect into their own subdirectory - this is then trivial to "protect". Having a mixture of files you want to deny and allow access to in the current directory, whilst allowing all subdirectories is a bit of a code smell and inherently adds an additional layer of complexity.

Any mod_rewrite directives in subdirectories (eg. /blog/.htaccess) will naturally override this. In order to access other subdirectories you just need to make sure you only target the current directory.

For example:

Options -Indexes

RewriteEngine on

# Block all requests that target files in the current directory
# except for "index.php", "api.html" and "api_fetch.js"
# All virtual URLs are still allowed and passed through to the front-controller below
RewriteCond %{REQUEST_URI} !^/(index\.php|api\.html|api_fetch\.js)$
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^[^/]+$ - [F]

# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]

Aside: I realise this is pseudo-ish code, but...

:
<Directory /blog>
Allow from all
</Directory>
RewriteEngine off
  • The Allow, Deny and Order directives are deprecated on Apache 2.4 and should be replaced with the new Require (mod_authz_...) directives. These older directives have been moved to mod_access_compat and are provided for backwards compatibility only.

  • The <Director> container is not permitted in .htaccess, this can only be used in a server or virtualhost context.

  • The RewriteEngine off directive at the end of the file disables the rewrite engine for the entire file. (The last instance of this directives "wins".)

12
  • Use mod_rewrite to control access, instead of mod_auth... Why? Also, there seems to be some error with your logic since it forbids all file access.
    – Kirikan
    Jul 15 '20 at 15:50
  • Sorry, was missing a slash on the CondPattern. Basically, mod_rewrite gives you the fine grained control you require, the mod_authz_.... directives don't - when used in a directory context. You need access to the server config to do more. I've updated my answer.
    – MrWhite
    Jul 15 '20 at 15:55
  • There may be a better solution if we know more specifics about your system. For instance, what files are you wanting to protect and why?
    – MrWhite
    Jul 15 '20 at 15:56
  • Thanks, now it makes sense, so %{REQUEST_URI} is full request, including /? like t.co/my_request will be /my_request for $URI? As for what I'm trying to achieve - just general knowledge of basic security. Right now I have a few files user should be able to access in root + I want to make /blog/ where Wordpress is stricter but since WP is somewhat dynamic (especially wp-content and uploads) there are no 100% rules so I need to get general understanding of how such kind of protection usually is done so I can apply to other cases a swell.
    – Kirikan
    Jul 15 '20 at 16:08
  • Yes, the REQUEST_URI server variable contains the full URL-path, including the slash prefix. Unlike the URL-path that the RewriteRule pattern matches against, which does not include the slash prefix (because the directory-preifx, that ends in a slash, is first removed.) A slight complication in the code you've posted is that you have a front-controller that routes all virtual URLs to index.php - so whilst you are blocking some files, you need to allow all URLs that don't map to files.
    – MrWhite
    Jul 15 '20 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.