Limit Access to Image Folder

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Limit Access to Image Folder

Post by phanky5 »

Hi guys.

I am not sure whether or I should post this here. I have a security issue with pictures on my server. I am programming a social networking site. You can upload photo albums on that site. Now the user can limit pictures being shown on page. For example photo albums could be set to just be shown to friends of the user.

However I don’t know how I can prevent people from just opening the folder containing the images. This way somebody could get to the pics even though he/she is not allowed to see these pics.

Now my question: How can I prevent people from accessing the image folder? I want these images to only show if they are viewed through my website (where i can control what is shown with php/ sql). I don’t want people to be able to just open the source folder for those images and see everything that’s in there.

What would be the easiest way to accomplish this?

Thank you for your help guys. I hope somebody know the answer to that problem…
User avatar
Syntac
Forum Contributor
Posts: 327
Joined: Sun Sep 14, 2008 7:59 pm

Re: Limit Access to Image Folder

Post by Syntac »

Stick a .htaccess file in the directory.

Code: Select all

<files *>
        order deny,allow
        deny from all
        options -indexes
</files>
Then create a PHP script that retrieves an image and outputs it (since PHP isn't affected by .htaccess files).

Code: Select all

$data = file_get_contents("path/to/image.png");
header("Content-type: image/png"); // Or whatever the MIME type is.
echo $data;
This approach prevents the user from viewing an image that is not explicitly allowed by the application.
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Thanks a lot Syntac. That should do. I didn't know that php is not affected by the htacces file. That makes the whole thing a lot easier than I thought.
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Man I just realize this is not the way I want to handle things. Got to rewrite too much code to do that. Also it seems a little complicated to include pictures in my existing html with headers.

But .htaccess seems to be the way to go. In htaccess there is a way to deny certain URLs access to files like this:

files *>
order deny,allow
allow from WhatEverWebSite.com
</files>

However this is just working for Domains and IPs. I would like to allow access to this folder only from certain directories on my server. Something more like this:

files *>
order deny,allow
allow from MyWebsite.com/home/
allow from MyWebsite.com/photo-album/
</files>

Does anybody know how i could make this work in .htaccess? This would definitly be the easiest way for me to handle this matter. If anybody knows how to make the abouve work in .htaccess your help is greatly appreciated.

Thank you...
User avatar
Syntac
Forum Contributor
Posts: 327
Joined: Sun Sep 14, 2008 7:59 pm

Re: Limit Access to Image Folder

Post by Syntac »

Not sure what you're trying to do here. The approach I mentioned is probably the most secure.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Limit Access to Image Folder

Post by pickle »

If you modify ~Syntac's approach a bit, you shouldn't have to write too much code.

I imagine you're referring to all the code you have that references the images themselves. You can leave that as it is.

Set up the .htaccess file to serve up a PHP file instead of what the user requested. You can then use the PHP file to see if the user is authenticated, then forward the data like ~Syntac said.

You can still refer to the images by name (therefore leaving all of your code intact), and you can control access to the files and directory listing.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Hi guys.

Syntac, what I was trying to do above is probably impossible so I think we should just forget about this idea.

Here is what I am doing now to prevent people from checking out the pics by simply opening the image folder with all pics in it.

Ok I got that image folder on my server. Now I made this image folder a subdomain. So I got do domains now.

1. Mydomain.com
2. Images.Mydomain.com

Mydomain.com goes to my page root and Images.Mydomain.com goes to the image folder directly.
So there are two ways to get to my images now.

I could do:

http://www. Mydomain.com/images/whateverimage.jpg

Or I could do:

http://www. Images.Mydomain.com/whateverimage.jpg

Both go to the same pic.

Then I modified apache a little.

1. I added a hotlink protection to all images of whatever format to my website(+plus of course subdomain cause it’s in there too right?)

You can see that here:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)? Mydomain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]

Notice that I only allow delivering images to my main domain. They won’t show if I try to open them from my subdomain Images.Mydomain.com.

So now I can still use all existing code. (All the pics have an SRC= Mydomain.com/images/whatever.jpg and of course they are all delivered on my main domain.)

So as long as I open those pics SRCs from my main domain everything is fine (and I can control everything in here). But people could still open the containing image folder and see all pics. Now step two comes into play…

2. I redirected all requests to the image folder(in URL) to my subdomain. So if somebody tries to open Mydaomain.com/images/ in his browser he will get redirected to images.Mydomain.com/.
Now this goes to the same image folder but the potential attacker is on the subdomain now. And the subdomain won’t deliver any pics. DONE!!!

The redirect for apache is here:

Redirect /images http://www.images.mydomain.com

I like this approach a lot cause its very simple and I don’t need to touch any of my code on page. Maybe I am missing something here but this approach seems pretty secure to me. Anything I missed? What do you think?

Anyways guys I would still like to know how I could integrate your approach into my page. The thing I don’t understand is how I can put this into my HTML template. The only way to force “Content-type” I know is with the header like Syntac suggested. In this case I could only deliver a pic on an otherwise empty page. I probably just don’t know how to integrate this properly. There must be another way than using “header” right?

Pickle, could you write a view lines of code to show me how I could integrate the pic into an existing HTML template with this approach? I would really like to know how to do it.

Is there any loop whole I didn’t think of in the approach I have taken now? The only thing I could think of would be to post HTML code on my page. Like to post some <img> stuff on my page. I will just strip those things out of any posts on my page if they go to my image folder. Anything else I might have missed?
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Ohh I think I forgot something. With the approach I have taken now a potential attacker could still rewrite his browser to include some javascript on his page when he loads my page. In this case he could still inject pic URLs into my main Domain Mydomain.com. Assuming he knows the pic IDs(refering to the pic location) he could still see the pics. Now the pic URLs are generated with autoincrement in SQL when the pic is uploaded. So for one photo album they are running numbers and those are not hard to guess right? In this case my approach won't be all that secure.

Damn this seems complicated. Could you guys please give an example of how I can include your approach in an HTML template/ without useing header? I cant use header because I dont want the pics to show on an empty page. I want them to show inside some other HTML code so I can add a design around it.

Any suggestions? Please help me out here guys.

The only other way that comes to mind to protect the pics with the approach I have taken now is to make the autoincrement ID of the pic choose the IDs randomly and not one after another. Also the autoincrement ID numbers given by SQL would have to have a certain minimum length. How could I do this? Make the ID autoincrement but random? Is there a way? Well in this case somebody could off course still bruteforce the PIC IDs inside that javascript thing he would put on my page. So I guess to make it a bit more complicated the autoincrement ID given by sql would not just have to consist of numbers but special characters as well. Can SQL do this? Is it possible?

Otherwise this won't work.

Can somebody let me know how I could make one of the two approaches work?
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Limit Access to Image Folder

Post by pickle »

I imagine your current templates have lines like this:

Code: Select all

<img src = "http://mydomain.com/images/4938854.jpg" />
Leave them that way.

In your .htaccess file, put a file like this (I can't write .htaccess files from memory yet, so this will need to be cleaned up likely)

Code: Select all

RewriteEngine on
Rewrite ^.jpg$ proxy.php
The idea is not to forward requests with a redirect, but rather do a rewrite so requests are none-the-wiser.

In you PHP file, first check if the user requesting the file is authenticated or not. If not, you can just exit(). If they are, use $_SERVER[] to determine the filename the user wants, then header() and readfile() to make the PHP file pretend to be that image.

It's impossible to make images only viewable in a template & not individually. The request to the server is exactly the same regardless. I don't really see a problem with that anyway - if a user is allowed to see an image, let them see the image any way they want.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Hi pickle.

Thanks a lot for you help. I got the idea of how this is supposed to work now. There is just one thing I cant get to work. How do i get the location of the requested pic from $_SERVER[]? Everything is working like a charm but i can't get the location of the pic to be passed by $_SERVER[]. I tried to pass it inside the htaccess rewrite. This is working but as soon as I close down the whole image folder the way Syntac suggesed (i still dont want people to see what is contained in image folders, maybe single pics but not a listing of all pic locations) this approach of course stops working too.

I checked on php.net for different ways to use $_SERVER[] for this. But I couldnt find anything that got me the results i wanted. I would appreciate if you could tell me how to get this done.

Maybe you are interessted to know that I got my own approach to work right now. As I said I put all images on a subdomain. Then i closed this subdomain with a hotlink protection for all images in it in .htaccess. Pictures now only get served on my main domain. Before I had the problem that people could still post html for images into my page or inject javascript etc on that main domain to get to pictures they should not see. I also closed this possibility now. I just changed the name of all picture uploads to include random strings i store on my db. So now a pic name would be something like:

userId_20random_charachters_here.jpg

So people cant know the pic locations unless they are delievered by my db. I also closed down the folders containing the pics. I have rewritten htaccess to rewrite all request in the image folder to 404 error page if no complete pass to an existing image location is requested (missing .jpg .png etc.). So now you cant even see the folder structure anymore.

So I would say this is pretty much secure now.

Still I would like to know how I could implement your solution as it offers additional protection. Please let me know how i can get the pic location requested from $_SERVER[].

I got another question though. Wouldnt it use up a lot of server resources(memory) to run all pictures through readfile()? Just not sure about that as i don't really understand whats going on inside the server.
User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: Limit Access to Image Folder

Post by pickle »

Make the PHP file look like this:

Code: Select all

<pre>
<?PHP print_r($_SERVER); ?>
</pre>
And type the URL of a protected image into your browser. You should then see $_SERVER as the PHP file will have access to, when a redirection takes place. I'm not 100% what the field is, but it's something along the lines of "REQUEST_URI" that should contain the filename.

Yes, it will use up resources to run everything through readfile(). However, you're essentially asking for a permissions check on every image requested. I don't know of any other way than using PHP to do that permissions check then give the image data if allowed.
Last edited by pickle on Fri Nov 21, 2008 4:55 pm, edited 1 time in total.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
phanky5
Forum Newbie
Posts: 10
Joined: Sun Nov 16, 2008 2:20 pm

Re: Limit Access to Image Folder

Post by phanky5 »

Cool thanks. Gone play around a bit more with $_SERVER. About the server resources, I might eventually check image permissions for each single pic requested. That’s why I am asking. No offense I am just trying to understand all aspects of this approach.

Thanks again.
Post Reply