views:

394

answers:

5

Hi,

On my website I store user pictures in a simple manner such as: "image/user_1.jpg".

I don't want visitors to be able to view images on my server just by trying user_ids. (Ex: www.mydomain.com/images/user_2.jpg, www.mydomain.com/images/user_3.jpg, so on...)

So far I have three solutions in mind:

  1. I tried using .htaccess to password protect the "images" folder. That helped me up to some point but some of the images started popping up a username and password request on my htmls (while amazingly some images did not) so this seems to be an unpredictable method.

  2. I can start converting my user_id's to an md5 hash with some salt. The images would be named as: /image/user_e4d909c290d0fb1ca068ffaddf22cbd0.jpg. I don't like this solution. It makes the file system way complicated.

  3. or I can user PHP's readfile() function or maybe something similar in Perl or Python. For instance I could pass a password using an md5 string to validate visitors as loggedin users with access to that image.

I'm leaning towards option 3 but with a Perl or Python angle (assuming they would be faster than PHP). However I would like to see other ideas on the matter. Maybe there is a simple .htaccess trick to this?

Basically all I want to make sure is that no one can view images from my website unless the images are directly called from within htmls hosted on my site.

Thanks a lot,

Haluk

+2  A: 

You are right considering option #3. Use service script that would validate user and readfile() an image. Be sure to set correct Content-Type HTTP header via header() function prior to serving an image. For better isolation images should be put above web root directory, or protected by well written .htaccess rules - there is definitely a way of protecting files and/or directories this way.

Michał Rudnicki
Thank you, you are right I should definitely try to move my images out of the webroot.
Haluk
+6  A: 

Any method you choose to determine the source of a request is only as reliable as the HTTP_REFERER information that is sent by the user's browser, which is not very. Requiring authentication is the only good way to protect content.

Azeem.Butt
By authentication if you mean asking for a username and password each time an image is called I disagree. But if you mean "an authenticated session/login", I agree. I plan to pass the viewer_id, image_id and an md5 string to my python script. The python will already know the salt in the md5. It will merge the salt, the image_id, the viewer_id and come up with an md5 again. If the passed md5 string is a match then python will show the image. I can even consider dropping the md5 thing and coming up with my own small encryption (a multiplication of the viewer_id and the image_id maybe).
Haluk
+3  A: 

You can look up "Hotlinking prevention" via htaccess and i think that should be a simple solution for the type of protection you need. However its not fool proof , people who will really want to get those images will find a work around by faking the referrer.

http://altlab.com/htaccess%5Ftutorial.html

Sabeen Malik
I don't think what I'm looking for is called "hotlinking prevention". I believe that is to avoid my images to be called from another domain. It wouldn't restrict visitors to call my images using an address like: www.mydomain.com/image/1.jpg.
Haluk
You can remove the empty referrer allowed in the rule and that should work.
Sabeen Malik
+5  A: 

Method #1 is not viable as it will ask for user name and password on each and every image requested. You probably got the prompt for some of the images and not for others due to caching issues.

Method #2 looks the most appealing to me by being the least processor intensive, but with only the user_id passed through the md5 function the file name still quite easily guessable. You should go for md5('my secret string'.$user_id) for a better solution.

Why are you picking #3 via Perl or Python? What's wrong with PHP's speed? Indeed if you're protecting your images this way you should go to the extra length of moving them out and above your webroot so they're only accessible via your script which first checks if the user is authenticated and then passes the avatar by reading it and outputting it. Alternatively, you could protect the directory with an htaccess file saying deny from all.

Plus you should go for a HTTP_REFERER security either via PHP or via .htaccess.

Good luck!

kitsched
Good catch on method 1. Probably caching allowed me to see the images. Method 2. I would definitely use a salt if I am to use it. Method 3: I've read several benchmarks showing Python and Perl are faster than PHP. That's why I thought I could throw the load onto either one of them. I will definitely do my own benchmark before I choose the best one but here is one example benchmark (the top answer): http://stackoverflow.com/questions/62333/python-vs-php-python-runs-slower
Haluk
Haluk: Speed depends on method to run your program. mod_perl would be fastest, any language as FastCGI should be fast enough, any language as CGI (like most hosting services would provide you, independent of language) may be fast enough. Benchmarks are very content-dependent.
Alexandr Ciornii
A: 

As has been said hotlinking protection does not protect your files from listing just by altering their id. Plus Refferer can be easily faked.

In this case I would recommend some kind of authentication. You must create PHP script that will serve images only if it verify logged user via COOKIES or SESSION. (I wouldn't recommend using md5 of user password).

Maybe you'll need some SQL table to save access permissions.

Oh and to protect your images you can just place .htaccess with

deny from all

to the images folder.

Petr Peller