75

I'm making a website which allows people to upload files, html pages, etc... Now I'm having a problem. I have a directory structure like this:

-/USERS
    -/DEMO1
    -/DEMO2
    -/DEMO3
    -/etc... (every user has his own direcory here)
-index.php
-control_panel.php
-.htaccess

Now I want to disable PHP, but enable Server-side includes in the direcories and subdirectories inside /USERS

Can this be done (and if so, how)?

I use WAMP server

starball
  • 20,030
  • 7
  • 43
  • 238

11 Answers11

130

Try to disable the engine option in your .htaccess file:

php_flag engine off
Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • What happens when someone browses to file in the web browser? Does the source code show? – Lance Rushing Aug 13 '09 at 15:48
  • 10
    @Lance Rushing: The file’s content will be send to the client. But why don’t you just try it yourself to see what happens? – Gumbo Aug 13 '09 at 16:10
  • 22
    Note that this will give a 500 error if PHP is not installed as mod_php. Wrap it in `` ... ``. – Halil Özgür Oct 20 '11 at 07:47
  • 4
    its ok to use `php_admin_flag` instead, This can not be used in .htaccess files. Any directive type set with php_admin_value can not be overridden by .htaccess or ini_set(). To clear a previously set value use none as the value. – pylover May 02 '14 at 07:11
  • 8
    But can someone create a sub-directory and place a "php_flag engine on" in a new .htaccess then run a PHP code from this sub directory? – user5858 Nov 22 '14 at 08:15
  • 1
    @user5858 Yes, that would be possible. – Gumbo Nov 22 '14 at 08:17
  • @Gumbo .. how to disallow this? – user5858 Nov 22 '14 at 08:20
  • 1
    @user5858 You can’t do this with an .htaccess file, only in server/virtual host configuration. You could, for example, disallow the override by .htaccess files with [`AllowOverride`](http://httpd.apache.org/docs/current/mod/core.html#allowoverride). – Gumbo Nov 22 '14 at 08:24
  • 1
    It also stops serving js/css content from that folders. How to stop only php and allow js/css? – RN Kushwaha Sep 09 '15 at 15:16
  • When I tried this, even raw JPG files within the folders/sub-folders were no longer being pulled out, returning 404. – jeffkee Mar 28 '16 at 23:03
  • 1
    I use this code, and all php files can't execute anymore, but the problem is that I can't undo this horror effect, mysite is down and I don't know how to fix this sheet :O I remove the code, and .htaccess but nothing happened. help please – Mohad Hadi May 21 '16 at 13:04
  • 3
    I would not recommend using this at all. As some have pointed out, this allows people to download the content of your PHP files. This in my opinion, is very insecure and should never be done. – Pierre-Olivier Benoit Sep 11 '18 at 08:47
  • I used in Centos 6.10 for multiple folders in virtual host .conf definitioin file: ``` php_admin_value engine Off ``` However, even though it doesn't parse php code the usual way it still outputs from a .php things such as varable declarations and text when doing echo e.g. ```PHP CODE EXECUTED!!"; $a=1; $b=2; echo $a+$b;``` - this produces in web browser: "PHP CODE EXECUTED!!"; $a=1; $b=2; echo $a+$b; " – webcoder.co.uk Apr 27 '21 at 13:14
  • `php_flag engine off` stopped working since I migrated to `php-fpm`. See answer https://stackoverflow.com/a/62514989/923560 for what to do when using `php-fpm`. – Abdull Sep 05 '22 at 17:29
  • @Pierre-OlivierBenoit Never say never, there are cases when it should be used, for ex for directories where you allow users to upload stuff and then download them later. – soger Dec 22 '22 at 13:51
51

To disable all access to sub dirs (safest) use:

<Directory full-path-to/USERS>
     Order Deny,Allow
     Deny from All
 </Directory>

If you want to block only PHP files from being served directly, then do:

1 - Make sure you know what file extensions the server recognizes as PHP (and dont' allow people to override in htaccess). One of my servers is set to:

# Example of existing recognized extenstions:
AddType application/x-httpd-php .php .phtml .php3

2 - Based on the extensions add a Regular Expression to FilesMatch (or LocationMatch)

 <Directory full-path-to/USERS>
     <FilesMatch "(?i)\.(php|php3?|phtml)$">
            Order Deny,Allow
            Deny from All
    </FilesMatch>
 </Directory>

Or use Location to match php files (I prefer the above files approach)

<LocationMatch "/USERS/.*(?i)\.(php3?|phtml)$">
     Order Deny,Allow
     Deny from All
</LocationMatch>
tkeeler
  • 100
  • 9
Lance Rushing
  • 7,540
  • 4
  • 29
  • 34
  • 2
    "dont' allow people to override in htaccess", yes, this is a very good one. All the work in your htaccess will be wasted if people can simply override it with a local htaccess file. Your demo enviroment probably has no use for php files, so you're best not allowing them to be created or served at all (not even source code view), simply block them entirely (including htaccess files) – Timo Tijhof Feb 12 '12 at 23:52
  • Excellent comment, I had overlooked the idea that people could upload a ".htaccess" file. – bart Jan 10 '14 at 09:33
  • 1
    This does not work in a .htaccess file (got error 500). It should be added to the vhost of apache conf. – NicolasBernier Oct 10 '14 at 09:24
  • may I suggest even a shorter regex to cover for all php1-php5 etc and phtml: `"(?i)\.(ph.+)$"` – Aleksey Napolskih Mar 13 '15 at 23:42
  • As mentioned, this does not work for .htaccess files and needs to be put in the vhost config of apache. For the first example to work in a .htaccess file, simply use: `Order Deny,Allow` `Deny from All` – Pierre-Olivier Benoit Sep 11 '18 at 08:49
13

If you're using mod_php, you could put (either in a .htaccess in /USERS or in your httpd.conf for the USERS directory)

RemoveHandler .php

or

RemoveType .php

(depending on whether PHP is enabled using AddHandler or AddType)

PHP files run from another directory will be still able to include files in /USERS (assuming that there is no open_basedir restriction), because this does not go through Apache. If a php file is accessed using apache it will be serverd as plain text.

Edit

Lance Rushing's solution of just denying access to the files is probably better

Tom Haigh
  • 57,217
  • 21
  • 114
  • 142
11
<Directory /your/directorypath/>
     php_admin_value engine Off
</Directory>
Domus
  • 143
  • 1
  • 2
9

This will display the source code instead of executing it:

<VirtualHost *>
    ServerName sourcecode.testserver.me
    DocumentRoot /var/www/example
    AddType text/plain php
</VirtualHost>

I used it once to enable other co-worker to have read access to the source code from the local network (just a quick and dirty alternative).

WARNING !:

As Dan pointed it out sometime ago, this method should never be used in production. Please follow the accepted answer as it blocks any attempt to execute or display php files.

If you want users to share php files (and let others to display the source code), there are better ways to do it, like git, wiki, etc.

This method should be avoided! (you have been warned. Left it here for educational purposes)

lepe
  • 24,677
  • 9
  • 99
  • 108
  • 2
    Massive security hole! Don't do in production! – Dan Garland Dec 21 '16 at 13:33
  • @DanGarland Please tell us how?\ – Airy Apr 29 '17 at 22:13
  • 1
    @AbdulJabbarWebBestow The reason is because anyone would be able to view the souce code instead of executing it. If those codes contain sensitive information (like connection passwords), that information can be considered compromised. – lepe May 01 '17 at 02:26
  • @DanGarland I just saw the code he has mentioned the root folder for text/plain. You are absolutely right. And I can see Lepe has edited his answer and accepted your point. – Airy May 01 '17 at 09:38
  • 2
    That "security hole" is a matter of usage: putting `AddType text/plain php` in the directory where user uploaded content is stored might be an interesting security guard to have: if user manage to upload a PHP file, then it won't be executed by the server, sure they'll see the PHP source code, but from a file they uploaded – Xenos Sep 06 '19 at 09:33
9

None of those answers are working for me (either generating a 500 error or doing nothing). That is probably due to the fact that I'm working on a hosted server where I can't have access to Apache configuration.

But this worked for me :

RewriteRule ^.*\.php$ - [F,L]

This line will generate a 403 Forbidden error for any URL that ends with .php and ends up in this subdirectory.

@Oussama lead me to the right direction here, thanks to him.

Fabien Quatravaux
  • 3,737
  • 2
  • 27
  • 33
2

If you use php-fpm, the php_admin_value will NOT work and gives an Internal Server Error.

Instead use this in your .htaccess. It disables the parser in that folder and all subfolders:

<FilesMatch ".+\.*$">
    SetHandler !
</FilesMatch>
Daantje
  • 2,406
  • 25
  • 26
1

This might be overkill - but be careful doing anything which relies on the extension of PHP files being .php - what if someone comes along later and adds handlers for .php4 or even .html so they're handled by PHP. You might be better off serving files out of those directories from a different instance of Apache or something, which only serves static content.

Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
1

On production I prefer to redirect the requests to .php files under the directories where PHP processing should be disabled to a home page or to 404 page. This won't reveal any source code (why search engines should index uploaded malicious code?) and will look more friendly for visitors and even for evil hackers trying to exploit the stuff. Also it can be implemented in mostly in any context - vhost or .htaccess. Something like this:

<DirectoryMatch "^${docroot}/(image|cache|upload)/">
    <FilesMatch "\.php$">
        # use one of the redirections
        #RedirectMatch temp "(.*)" "http://${servername}/404/"
        RedirectMatch temp "(.*)" "http://${servername}"
    </FilesMatch>
</DirectoryMatch>

Adjust the directives as you need.

0

I use in Centos 6.10 for multiple folders in virtual host .conf definitioin file:

<DirectoryMatch ^/var/www/mysite/htdocs/(nophpexecutefolder1|nophpexecutefolder2)>
       php_admin_value engine Off
</DirectoryMatch>

However, even though it doesn't parse php code the usual way it still outputs from a .php things such as variable declarations and text when doing echo e.g.

<?php

echo "<strong>PHP CODE EXECUTED!!";

$a=1;
$b=2;

echo $a+$b;

The above produces in web browser?

PHP CODE EXECUTED!!"; $a=1; $b=2; echo $a+$b;

This could potentially expose some code to users which isn't ideal.

Therefore, it's probably best to use the above in combination with the following in .htaccess:

<FilesMatch ".*.(php|php3|php4|php5|php6|php7|php8|phps|pl|py|pyc|pyo|jsp|asp|htm|html|shtml|phtml|sh|cgi)$">
 Order Deny,Allow
 Deny from all
  #IPs to allow access to the above extensions in current folder
  # Allow from XXX.XXX.XXX.XXX/32 XXX.XXX.XXX.XXX/32
</FilesMatch>

The above will prevent access to any of the above file extensions but will allow other extensions such as images, css etc. to be accessed the usual way. The error when accessing .php:

Forbidden

You don't have permission to access /nophpexecutefolder1/somefile.php on this server.
webcoder.co.uk
  • 341
  • 3
  • 5
0
<Files *.php>
    Order deny,Allow
    Deny from all
</Files>
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93