3

This is essentially a duplicate of this question but with one caveat: I want to deny direct access to all files named index.php below the root directory.

Allow: /index.php

Deny: /application/views/settings/index.php

I know I can use PHP to look for a defined constant or variable, but is it possible to achieve this using .htaccess only? This is what I have so far:

##
# Disallow direct access to files.
#

<FilesMatch "^(.*)\.php$">
    Order Deny,Allow
    Deny from all
</FilesMatch>

<FilesMatch "^index\.php$">
    Order Allow,Deny
    Allow from all
</FilesMatch>

Adding a third FilesMatch to deny "^(.*)/index/index\.php$" does not work.

Community
  • 1
  • 1
josocblaugrana
  • 215
  • 4
  • 7
  • Why do you want to do this? There may be a better way to achieve what you want. – Pekka Nov 06 '12 at 12:57
  • It is for an MVC application. All controllers have a corresponding directory inside `/application/views`, with the default view always being named "index". It is not a big deal – I can always name it "default" or something else – but I would just like to know if it is possible to this with .htaccess. – josocblaugrana Nov 06 '12 at 13:03
  • 1
    So you want to prevent the index.php's being called directly? The way most frameworks do this is, they define a constant somewhere, then add a check for that constant in every file they don't want called directly: `if (!defined("CAN_RUN")) die ("This file can't be called directly.");` – Pekka Nov 06 '12 at 13:05
  • Yeah, I know. I just thought this could be done with .htaccess alone, and save a few lines of code in each file. – josocblaugrana Nov 06 '12 at 13:09
  • I would tend to put this in the PHP file for clarity's sake. It's a pretty kludgy htaccess rule; plus it won't work if you ever use a web server different from Apache, or if Apache is not configured with `AllowOverride All`. – Pekka Nov 06 '12 at 13:10

3 Answers3

2

You cannot do it with <FilesMatch or <Files> directive alone: you need to combine them with <Directory. For example:

<Directory /var/www>
  <FilesMatch "\.php$">
    Order Deny,Allow
    Deny from all
  </FilesMatch>
  <FilesMatch "^index\.php$">
    Order Allow,Deny
    Allow from all
  </FilesMatch>
</Directory>

<Directory /var/www/*>
  <FilesMatch "\.php$">
    Order Deny,Allow
    Deny from all
  </FilesMatch>
</Directory>

The catch here is that you should edit httpd.conf or similar files, as <Directory> directive cannot be used in .htaccess.

If you can't update .conf files and .htaccess is the only way around, you would have to copy the shown rule in each directory's .htaccess, I suppose. Whether or not it's better than using if(defined(...)) trick, is up to you.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
0

DEMO

(?<![^\/])\/index\.php

A quick regex, you may want something more accurate.

Javier Diaz
  • 1,791
  • 1
  • 17
  • 25
0

So you want to prevent the index.php's being called directly?

The way most popular web apps do this is, they define a constant somewhere, then add a check for that constant in every file they don't want called directly:

In the main file that can be called directly, and that includes the other index.php files, do:

define ("CAN_RUN", true);

In every sub-file that you don't want called directly:

if (!defined("CAN_RUN")) die ("This file can't be called directly.");
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • Don't the most frameworks separate application files from public scripts instead (so the former are inaccessible from `/public` directory)? – raina77ow Nov 06 '12 at 15:11
  • @raina77ow that's indeed the very best way to go where possible. I meant to say most popular *web apps* like WP, of which most don't have this separation - at least not properly. – Pekka Nov 06 '12 at 15:14