143

I have the following .htaccess file:

RewriteEngine On
RewriteBase /

# Protect the htaccess file
<Files .htaccess>
Order Allow,Deny
Deny from all
</Files>

# Protect log.txt
<Files ./inscription/log.txt>
Order Allow,Deny
Deny from all
</Files>

# Disable directory browsing
Options All -Indexes

I am trying to forbid visitors to access the following file:

domain.example/inscription/log.txt

but what I have above does not work: I can still access the file from the browser remotely.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Timothée HENRY
  • 14,294
  • 21
  • 96
  • 136

6 Answers6

240

Within an htaccess file, the scope of the <Files> directive only applies to that directory (I guess to avoid confusion when rules/directives in the htaccess of subdirectories get applied superceding ones from the parent).

So you can have:

<Files "log.txt">  
  Order Allow,Deny
  Deny from all
</Files>

For Apache 2.4+, you'd use:

<Files "log.txt">  
  Require all denied
</Files>

In an htaccess file in your inscription directory. Or you can use mod_rewrite to sort of handle both cases deny access to htaccess file as well as log.txt:

RewriteRule /?\.htaccess$ - [F,L]

RewriteRule ^/?inscription/log\.txt$ - [F,L]
Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • If your using IIS, do this in the web.config file instead. – Shaun Luttin Nov 03 '14 at 16:33
  • 1
    Using the rewrite rules denies my own code from accessing the contents of *.txt. How would you get around this? – Pantss Dec 06 '15 at 05:34
  • 11
    "the scope of the `` directive only applies to that directory" - no it doesn't. It applies to that directory _and_ all subdirectories below it. So `` will catch `/log.txt` _and_ `/inscription/log.txt`. – MrWhite Jan 30 '17 at 15:45
  • 1
    Can you update this answer since `Order Allow,Deny` is deprecated in 2.4? – jarrodwhitley Nov 02 '18 at 15:04
21

Strong pattern matching — This is the method that I use here at Perishable Press. Using strong pattern matching, this technique prevents external access to any file containing “.hta”, “.HTA”, or any case-insensitive combination thereof. To illustrate, this code will prevent access through any of the following requests:

  • .htaccess
  • .HTACCESS
  • .hTaCcEsS
  • testFILE.htaccess
  • filename.HTACCESS
  • FILEROOT.hTaCcEsS

..etc., etc. Clearly, this method is highly effective at securing your site’s HTAccess files. Further, this technique also includes the fortifying “Satisfy All” directive. Note that this code should be placed in your domain’s root HTAccess file:

# STRONG HTACCESS PROTECTION
<Files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>
Yashar Khavan
  • 1,615
  • 1
  • 17
  • 14
  • 1
    I get a 500 internal server error when using this code. Any idea why? I'm using Wordpress. – KVDD Jan 26 '15 at 21:25
  • 11
    Wouldn't it make more sense to just disallow users from accessing dotfiles? Using something like ``. – Steen Schütt Nov 15 '16 at 09:12
  • 1
    Need a space between tilde and first quote mark—at least for me I needed it. ~ SPACE " – Art Geigel Apr 30 '20 at 20:45
  • 2
    I obtained the same behavior disabling .files: order allow,deny deny from all – Pinonirvana Jun 25 '20 at 12:28
  • "containing “.hta”, “.HTA”, or any case-insensitive combination" - But that's only necessary if you are running on a case-insensitive filesystem like Windows, and it's unlikely you'd be running Apache on Windows in a production environment. `^\..*` - You don't need the trailing `.*` if you just want to block dot-files. `^\.` will do the job (and is shorter and more efficient). `^.*\.([Hh][Tt][Aa])` - Likewise, you don't need the `^.*` prefix here, for the same reason a trailing `.*` is not required (and not used). – MrWhite Feb 26 '23 at 00:52
  • Please give credit when you copy/paste [someone else's work](https://perishablepress.com/improve-site-security-by-protecting-htaccess-files/comment-page-2/). – Ian Dunn Mar 14 '23 at 21:07
17

I don't believe the currently accepted answer is correct. For example, I have the following .htaccess file in the root of a virtual server (apache 2.4):

<Files "reminder.php">
require all denied
require host localhost
require ip 127.0.0.1
require ip xxx.yyy.zzz.aaa
</Files>

This prevents external access to reminder.php which is in a subdirectory. I have a similar .htaccess file on my Apache 2.2 server with the same effect:

<Files "reminder.php">
        Order Deny,Allow
        Deny from all
        Allow from localhost
        Allow from 127.0.0.1
     Allow from xxx.yyy.zzz.aaa
</Files>

I don't know for sure but I suspect it's the attempt to define the subdirectory specifically in the .htaccess file, viz <Files ./inscription/log.txt> which is causing it to fail. It would be simpler to put the .htaccess file in the same directory as log.txt i.e. in the inscription directory and it will work there.

MrWhite
  • 43,179
  • 8
  • 60
  • 84
Nik Dow
  • 584
  • 4
  • 10
4

Place the below line in your .htaccess file and replace the file name as you wish

RewriteRule ^(test\.php) - [F,L,NC]
Community
  • 1
  • 1
Rakesh Dongarwar
  • 475
  • 7
  • 10
1

On Apache 2.4, if you want to deny access to a specific file (or URL-path) in a subdirectory then you can use an Apache expression in an <If> container. For example:

<If "%{REQUEST_URI} == '/inscription/log.txt'">
    Require all denied
</If>

Reference:

MrWhite
  • 43,179
  • 8
  • 60
  • 84
-4

Well you could use the <Directory> tag for example:

<Directory /inscription>
  <Files log.txt>
    Order allow,deny
    Deny from all
  </Files>
</Directory>

Do not use ./ because if you just use / it looks at the root directory of your site.

For a more detailed example visit http://httpd.apache.org/docs/2.2/sections.html

  • 2
    But a `` container is not permitted in `.htaccess`. In `.htaccess`, the `.htaccess` file itself is the "_Directory_ container" (per-directory config file). – MrWhite Jan 30 '17 at 13:47
  • Well then you could use the Redirect. `Redirect /inscription/log.txt access_denied.html` This will redirect the user to `access_denied.html` if the user goes to `inscription/log.txt` in the inscription directory. – Nicholas English Jan 30 '17 at 14:47