.htaccess prevents access to various files that are not supposed to be downloaded by users, including CVS's control files in the CVS directory: Entries, Root and Repository. In #28776: Protect svn files in .htaccess, the pattern was expanded to control files used by Subversion. I suggest this is extended to also cover files used by Git.

Unfortunately, we cannot use <DirectoryMatch> in .htaccess. The previous approach has been to include the names of files used by CVS and Subversion, but this isn't possible for Git, because the .git directory and its subdirectories may contain files with more or less any name.

I don't know whether the current list of filenames for CVS and Subversion is complete either (though #105851: finish hiding CVS/* files in .htaccess suggests that it is for CVS).

This patch suggests a new approach. If mod_rewrite is enabled, access to the complete directory is prohibited using a RewriteRule (credit). Otherwise, access to some of the known filenames is blocked using <FilesMatch>.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

c960657’s picture

Status: Active » Needs review
wretched sinner - saved by grace’s picture

Is it worth also expanding this for hg, bzr and any other common version control systems? Otherwise we will end up with a plethora of issues for these.

moshe weitzman’s picture

Seems like a very good idea.

wretched sinner - saved by grace’s picture

Status: Needs review » Needs work

based on #3

c960657’s picture

Title: Protect .git directory in .htaccess » Protect .git, .hg and .bzr directories in .htaccess
Status: Needs work » Needs review
FileSize
2.16 KB

Seems like Mercurial uses a .hg directory, and Bazaar a .bzr directory, so that's pretty easy in the mod_rewrite case. I don't know whether it is possible to enumerate all possible file names in the directories, but the list of files easily gets very big.

Here is my suggestion: For CVS, we provide a complete list of filenames, while Subversion, Git, Mercurial and Bazaar are only protected by the mod_rewrite approach. CVS get this special treatment, because it is the VCS used by Drupal itself. This removes the special treatment that Subversion has gotten so far.

Also, in FilesMatch we block access to all files beginning with a period. This includes .cvsignore, .gitignore etc. as well as various temporary files created by CVS, Vim etc.

cburschka’s picture

Maybe this should just be generalized to all directories prefixed by a dot?

Re-test of vcs-htaccess-2.patch from comment #5 was requested by wretched sinner....

wretched sinner - saved by grace’s picture

Priority: Normal » Critical
Status: Needs review » Reviewed & tested by the community

Tested and works as expected. Bumping priority as this will effect lots of people.

webchick’s picture

Category: feature » task
Priority: Critical » Normal
Status: Reviewed & tested by the community » Needs work

Hm. Is there a more generic way to handle this? Like excluding all files/directories that begin with a "."? This looks pretty dirty, and we'll need to keep maintaining it over time.

Also, critical is for "Drupal is actively dripping blood from its eyeballs." This doesn't remotely qualify. I don't think there's anything in these files that exposes anything security-wise, and even if so, people smart enough to use bzr/git/etc. can figure out their own re-write rules.

c960657’s picture

Status: Needs work » Needs review
FileSize
2.36 KB

This blocks access to all directories whose names begin with a period.

I don't think there's anything in these files that exposes anything security-wise

AFAIK Git contains the complete source code in these directories. But I agree—this does not qualify as critical.

reglogge’s picture

Status: Needs review » Reviewed & tested by the community

Can confirm that this patch protects my .git directory which i deliberately placed in the webroot (big no-no under previous circumstances) when mod_rewrite is on. Same should be true for .hg, .svn, and .bzr since it's a generic rule protecting all directories beginning with a dot.
Files beginning with a dot are effectively protected by the FilesMatch directive.

Marking RTBC.

reglogge’s picture

Status: Reviewed & tested by the community » Needs review

sorry, RTBC'd too early, since I just read that two people have to sign off on a patch before RTBC-ing. Patch really works though :-)

moshe weitzman’s picture

Status: Needs review » Reviewed & tested by the community

RTBC.

c960657’s picture

scor’s picture

+++ .htaccess	15 Jan 2010 22:08:34 -0000
@@ -56,18 +56,32 @@ DirectoryIndex index.php index.html inde
+  # ¶
+  # If you do not have mod_rewrite installed, you should remove these
+  # directories from your webroot or otherwise protect them from being
+  # downloaded.
+  RewriteRule "(^|/)\." - [F] ¶

2 minor whitespaces issues

c960657’s picture

FileSize
2.37 KB

Fixed whitespace.

webchick’s picture

Version: 7.x-dev » 6.x-dev
Status: Reviewed & tested by the community » Patch (to be ported)
FileSize
1.76 KB

Great! Much better. :) Fixed up some of the language there (spell out 'version control system', add a missing word) and committed to HEAD.

Here's the patch I committed. Marking down for 6.x. Doesn't seem to apply cleanly, though.

arhak’s picture

while at VCS, would .orig/.rej files worth be protected as well?

webchick’s picture

We can discuss that in a separate issue, but I kind of don't think so. It's one thing to protect against legitimate files that might be there if using certain deployment practices, but quite another to babysit people.

c960657’s picture

Status: Patch (to be ported) » Needs review
FileSize
2.42 KB

Status: Needs review » Needs work

The last submitted patch, vcs-htaccess-D6-1.patch, failed testing.

c960657’s picture

Status: Needs work » Needs review

#20: vcs-htaccess-D6-1.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, vcs-htaccess-D6-1.patch, failed testing.

pfrenssen’s picture

Status: Needs work » Needs review
FileSize
1.78 KB

Rerolled patch

Status: Needs review » Needs work

The last submitted patch, 581706-24.patch, failed testing.

wretched sinner - saved by grace’s picture

Status: Needs work » Fixed

Committed fix Feb 7: #581706 by c960657: Protect hidden directories (.git, .svn, etc.) in .htaccess.

scor’s picture

Status: Fixed » Needs work

This has not been committed to Drupal 6.x.

jlarky’s picture

FileSize
991 bytes

Maybe this should just be generalized to all directories prefixed by a dot?

Because of this generalization i have some pages on my site blocked. Their names is started with dot, so i have 403 Forbidden on them. I figured out, that rule RewriteRule "(^|/)\." - [F] is wrong, because it have to check whether name is file/directory name or should be passed to drupal.

But anyway, I still dont know what to do with line

<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\.*|Entries.*|Repository|Root|Tag|Template)$">

I think it will be more preferable write out every expected dot-whatever directory rather than simply ".*" like

<FilesMatch "\.(engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$|^(\.git.*|\.hg.*|\.bzr.*|\.svn.*|\.cvs.*|Entries.*|Repository|Root|Tag|Template)$">

it's includes files like .gitignore, so i think everything is under control :)

p.s. i'm using drupal 7, but as i can understand it's common bug, so i didn't start new issue for 7.0. Is it ok?

YesCT’s picture

I was wondering if blocking all things starting with a dot was too general also.

Gribnif’s picture

Version: 8.x-dev » 7.10
FileSize
748 bytes

Blocking all things starting with a dot is definitely too general, because:

  • It's perfectly valid to create a menu path, say in a view, that starts with a dot.
  • When the user does this and tries to access the URL, Apache puts up its Access Denied page. Drupal's code is never even called. This makes it VERY difficult for the user to figure out why their perfectly valid menu path fails.

I agree with the part of #28 which uses tests of "-f" and "-d" to ensure the thing being blocked exists in the filesystem first:

  RewriteCond %{REQUEST_FILENAME} -f
  RewriteRule "(^|/)\." - [F]
  RewriteCond %{REQUEST_FILENAME} -d
  RewriteRule "(^|/)\." - [F]

I am changing the version of this issue to 7.10, because the change is already live in D7, not in D6. The attached patch is for D7.

[Edit: I am withdrawing my patch. I incorrectly left out the modification to the long FilesMatch clause, and my patch would therefore not solve the problem. I now believe that the solution in #28 is the best course. It also applies cleanly to D8. I am resubmitting it for consideration with D8.]

Version: 6.x-dev » 7.10
Category: task » bug

The last submitted patch, 581706-htaccess-30.patch, failed testing.

jbrown’s picture

Version: 7.10 » 8.x-dev

Bugs are fixed in D8 then backported.

Gribnif’s picture

Status: Needs work » Needs review

#28: vcs-htaccess-7.patch queued for re-testing.

droplet’s picture

Version: 7.10 » 8.x-dev
Issue tags: +Needs backport to D6, +Needs backport to D7
FileSize
921 bytes

Leading .DOT in path should be working and let modules to use it. eg: #1661098: Autocomplete and words beginning with dot (.)

Attached a patch and tested:
- It blocked .git, .anything
- It allow example.com/.abc

forestmonster’s picture

Hunh. Stepping back for a moment, instead of blocking requests for individual files, it likely makes more security sense for us to create a whitelist of acceptable requests of Drupal; everything else would be ignored. That's because we can never cover all the bases in our FilesMatch rule (essentially our blacklist) of the files that an individual user, installing Drupal and then setting to work on their site, might leave littered around. We will always be playing catch-up.

It's true that creating and maintaining a whitelist is harder, since we have to overcome some habits: both Drupal core and contrib modules right now can arbitrarily create files, and will expect them to be delivered properly by the Web server software.

However we would have fewer habits to overcome, if modules could update this HTTP request whitelist upon creating a file.

Another option is user education, making sure that users know that any files placed in Drupal's docroot may be delivered by their Web server in response to any legitimate request.

boombatower’s picture

@forestmonster: thanks for bringing a fresh perspective to this.

Whitelisting is generally a better security practice and given that it is also not proper use to just drop files in the drupal root (although I know people commonly do so) this seems like a logical direction to take. People can always whitelist there odd files if they really want to.

barraponto’s picture

This will probably end the nasty "OMG, anyone can see Drupal's version by checking the CHANGELOG.txt security dripping blood from its eyes omg omg". As if we couldn't tell an opensource framework version by its CSS/JS.

Anyway, to get this rolling, we should whitelist:

* index.php
* core/install.php
* core/update.php
* sites/*/files/* (files, not dirs)
* robots.txt
* themes/modules css/js/img (other media?)

boombatower’s picture

Not sure how the redirect works with whitelisting since you can hit /install.php and it works fine. core/authorize.php?

forestmonster’s picture

And a related discussion is going on at #1907704: Restrict temporary files created by text editors.

forestmonster’s picture

mjpa’s picture

If you're going to whitelist sites/*/files/*, what happens when someone uses the UI to change where files are stored?

mfb’s picture

Issue summary: View changes

Drupal should support RFC 5785, which establishes a .well-known URI location: https://tools.ietf.org/html/rfc5785

These URIs are registered with IANA - https://www.iana.org/assignments/well-known-uris/well-known-uris.xhtml - and include for example .well-known/openid-configuration as described at http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig

So either .well-known needs to be whitelisted, or only specific hidden directories (.bzr .git .hg .svn etc.) should be blacklisted.

mfb’s picture

FileSize
2.19 KB

Updated patch at #34 to whitelist the .well-known path.

JvE’s picture

Status: Needs review » Needs work

I can't believe this has been sitting here like his since july 2012.
Droplets "tested" patch:

  RewriteCond %{REQUEST_FILENAME} -f
  RewriteCond %{REQUEST_FILENAME} -d
  RewriteRule "(^|/)\." - [F]

This is checking if the requested path is both a file AND a directory at the same time and thus will never block anything.

mfb’s picture

FileSize
2.2 KB

OK I added the [OR] flag to fix that..

mfb’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 45: htaccess.patch, failed testing.

mfb’s picture

Status: Needs work » Needs review

45: htaccess.patch queued for re-testing.

jhedstrom’s picture

Status: Needs review » Needs work
Issue tags: +Needs re-roll

Status: Needs work » Needs review

hass queued 45: htaccess.patch for re-testing.

mfb’s picture

FileSize
2.2 KB

rerolled

tim.plunkett’s picture

Issue tags: -Needs re-roll

The last submitted patch, 45: htaccess.patch, failed testing.

mfb’s picture

I'd really like to add support for the .well-known directory to D7 so I created #2408321: Support RFC 5785 by whitelisting the .well-known directory in hopes of getting this part of the patch in faster.

Mile23’s picture

Status: Needs review » Closed (won't fix)

Using Drupal 8.0.x I tried to access http://localhost:8888/.git and .hg and .bzr.

In all cases I got something this:

Forbidden

You don't have permission to access /.git on this server.

So therefore I'm calling this issue CWF. Please re-open if this is in error.

There's also some overlap with #2408321: Support RFC 5785 by whitelisting the .well-known directory