Why?

-If you use imagecache and filefield/imagefield with public files you have no way to restirct access to imagecache presets and the original files in the filefields.

-Using private is not an opinion when serving a lot of images like gallery overviews with up to 100 Thumbnails.

-You want to protect only some of the images, in general the big presets and originals in the filefield.

- You want only members to access the huge preset images

- You want to protect even free presets from power leeching or batch downloading. (implementation of a possible download limit/day).

The idea.

Taken from: http://drupal.org/node/540754

Create htaccess (drupal_write) files via admin settings interface with checkboxes to protect/unprotect a folder in /files.

Example: RewriteRule ^sites\/default\/files\/(filefield_uploads\/.*)$ index.php?q=system/files/$1 [L,QSA]
Rewrite clean urls, too

Create a custom permissions.php where only the part of the bootstrap process is loaded that is neccessary (im not quiet sure if file_download requieres a full bootstrap).

- route all files through that permissions.php, system_menu()

- check with file_download()

- permission ok, serve the file.

What do you think of this idea? Is it worth coding/contributing a module? What do you think about the security because files are still in public_html.

Comments

arhak’s picture

relying on mod_rewrite might be dangerous, eventually your host might get it down and you'll end up naked

OTOH you should also address non-clean-urls, otherwise I could reach your images through ?q=sites/default/files/... (remember the approach to steal images from ImageCache)

marcoka’s picture

yea the host could get it down, but not on a root where you have full access :)
yes non-clean urls must be considered.

What do you mean with "remember the approach to steal images from ImageCache"? You mean through a bug not yet detected? Yes that is possible for every module used: filefiled/imagefield/imagecache.

In general my idea is an attempt to use permissions on files with a bigger site. In private mode its not possible or not future proof (if your user count raises).
The only idea i have is through htaccess, other attemps would involve hacking filefield/imagecache to force them to save special marked presets/files outside the public_html.

Thanks for your ideas.

arhak’s picture

I meant that you can't forget non-clean-urls
because even when rewrites will be a requirement for your approach, non-clean-urls will still work and therefore allow to access the same files through other URLs (using their equivalent ?q=... version)
(which is the principle for the exploit of ImageCache)

marcoka’s picture

oh, i wasn´t aware of that. so the solution with an htaccess is extremely insecure. i hope i find a solution for that, because in private use drupal is pretty unusable for lots of images (would force me to change the cms system).

EDIT:

you mena that: http://drupal.org/node/796384

-> http://drupal.org/node/810642

jaypan’s picture

Out of curiosity, what makes it unusable when you use lots of images? I've only used the private file system on one site, and it didn't have a slideshow.

Contact me to contract me for D7 -> D10/11 migrations.

marcoka’s picture

if you use private file system and lots of images like a gallery (5000 to 100.000 images) with 30/60/90 thumbnails per page, you get a bootstrap for every image (correct me if im wrong) that will be a massive performance drop and server load (at least thats what i was told and what i learned during research).
it would be great if i am wrong ;)

arhak’s picture

well, I think it can be done, but you should be careful of letting that backdoor opened
nevertheless, as I said, relying on rewrite rules for security is not a strong concept, since a new totally unrelated rule might come in and brake previous ones easily
just be aware of your risks

marcoka’s picture

the alternative would be hacking imagecache and filefield to save files outside the docroot and then route all throug a custom access.php.

arhak’s picture

BTW yes, I was referring to the approach of #796384: ImageCache makes private filesystem straightforward accesible (security issue #1172)
(and can't see how it would be directly addressed by #810642: API for modifing destination of prefix)

marcoka’s picture

adressed? In the post it says:

"Using the applied patch, which adds 1 line to the code you can fix the problem we have described here very easy: #796384: ImageCache makes private filesystem straightforward accesible (security issue #1172)"

arhak’s picture

EugenMayer told us to check that issue (comment #15 #796384-15: ImageCache makes private filesystem straightforward accesible (security issue #1172))
and I replied "I don't clearly see how it could solve this issue" (bellow at comment #17)
because it takes care of returning the appropriated URL, but it doesn't block the opened backdoor

marcoka’s picture

I have tested this "imagecache backdoor" today and now i understand. Evil one. Makes my idea crushing itself.

mikeytown2’s picture

This is the issue; it only goes to index.php if the file doesn't exist. One would have to rewrite this to make it work.

  # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Off the top of my head code to serve the file if it meets certain requirements (not in the /sites/default/files/protected/ or /sites/default/files/imagecache/protected/ directory). This would require some kind of logic around imagecache paths.

  # If referencing a file or directory not in the protected dir then allow the file to be served
  RewriteCond %{REQUEST_URI} !(^(/sites/default/files/protected/.*|/sites/default/files/imagecache/protected/.*))
  RewriteCond %{REQUEST_FILENAME} -s [OR]
  RewriteCond %{REQUEST_FILENAME} -d
  RewriteRule .* - [L,QSA]

  # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Another idea would force all protected files to end in *-private.jpg. Then in htaccess disallow direct access to these files. This would get around the imagecache issue.

  # If referencing a file or directory that doesn't contain -private.jpg then allow the file to be served
  RewriteCond %{REQUEST_URI} !(.*-private\.jpg)$
  RewriteCond %{REQUEST_FILENAME} -s [OR]
  RewriteCond %{REQUEST_FILENAME} -d
  RewriteRule .* - [L,QSA]

  # Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
marcoka’s picture

Thank you for your idea miketown2. I think i will consider that as a possibility because my second idea seems to be impossible.
This is the post about the second idea: http://drupal.org/node/821634

So i think i have to do it as a pseudo private system (idea 1).

izmeez’s picture

subscribing

marcoka’s picture

That would be a visual concept:

http://www.screencast.com/users/e-anima/folders/Jing/media/281dd2cd-15d5...

But if i do it like that i think that no contrib. module will work with images in private (not without hacking every module). I think the file API is not made to do such a thing like i try to do.

marcoka’s picture

forget that because of the following:

* Needs rewriting or hacking of imagecache/filefield/upload path/tokens and other modules
* Need to hack them with modify global $conf to save files in /var/files
* Retheme all links of modules