CodeIgniter Forums

Full Version: Preventing direct access to images... or something...?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]crikey[/eluser]
Hi all

I'm in the planning (pencil and paper) stage of my application, so sorry about the vagueness of my question and lack of code samples.

My app will allow users to upload items to a database. An "item" consists of data and an image associated with the item. Pretty basic. Two pieces of data that will be stored for an item is the user_id of the user adding the item, and a value that determines if the item is "public" or "private".

I would store the image as somepath/images/user_id/filename.jpg where filename is a random string of about 12 alphanumeric characters.

Registered and "guest" users of the application can search for items, and matching items will be listed in the results (only if "public"), including a thumbnail of each item's image, linking to the full-size image. Logged-in users can search and "public" items plus "private" items that match their user_id (using sessions I guess) will be included in the results.

My question is, because the HTML for the search results will include the image paths, what can I do to prevent someone who views the page source from typing lots of different combinations of filenames in the url and possibly getting an image associated with a "private" item?

Is there a programming or IA technique that is typical for such a thing?

Oh, I'm very new to PHP too, so if the solution is real obvious, don't be too hard on me!

Cheers

El Forum

[eluser]simpleCoder[/eluser]
Check out this post http://forums.htmlhelp.com/lofiversion/i.../t929.html . Hope this helps :-)

El Forum

[eluser]crikey[/eluser]
@simpleCoder:
Hmmm... looked like a thread with a whole bunch of people arguing about it, but no real solution. Thanks for taking the time though.

I guess the ideal solution would involved "protecting" the folder/images using some sort of access control, rather than "hiding" them. Just not sure how it would be done.

Ta.

El Forum

[eluser]coolfactor[/eluser]
I subclassed the Router library and added a special "img" shortcut. Whenever a route beginning with /img/ was encounted, the Router would search for a corresponding image in a designated location, and then pass that back to the browser. It's slightly slower, but offers protection.

Code:
/img/some_image.jpg

The Router determines the file is a JPEG image, sends the appropriate headers, and then fpassthru's the file.

El Forum

[eluser]crikey[/eluser]
coolfactor, I'm just wondering how that protects the file. I mean, although the actual location is hidden, I could guess (even by brute force) a filename that would successfully find a corresponding file in the "designated location".

Or am I missing something?

Thanks.

El Forum

[eluser]rogierb[/eluser]
you can always stream the image.

Whith that I mean you have an image.php which you call like
Code:
<img src="image.php?imagename.gif">

The image.php opens the image and outputs its contents.
Not to fast but very secure. Its the same technique as is used for captcha images.

El Forum

[eluser]xwero[/eluser]
You could write a cronjob to rename the image random every other hour or so and link the images in a database so you can call them in your php code.

It's not bulletproof but it would lessen the chance of finding an image by brute force attacks and if they find an image within the hour it would not be accessible anymore.

El Forum

[eluser]Jim OHalloran[/eluser]
[quote author="crikey" date="1188979557"]My question is, because the HTML for the search results will include the image paths, what can I do to prevent someone who views the page source from typing lots of different combinations of filenames in the url and possibly getting an image associated with a "private" item?[/quote]

Whenever I've had to solve this problem, this is what I did.... All of the images will need some sort of unique identifier, which can be something like the filename, an autoincrement number, the MD5/SHA1 hash of the file itself, doesn't matter as long as it's unique. I'll refer to this as the "image id" for the rest of the post.

Then store the images outside the site's web root ensuring that no one can access them without going through your script. Create a script which takes an image id, performs the necessary permissions checks, then makes a header() call to set the appropriate MIME type and echo out the file content to the browser. In CI you'd do this in a controller method and pass the image id in one of the URL segments.

That ensures the images can't be accessed by people URL guessing id's and trying to bypass the access controls. If your image ID is sequential (i.e. increments by 1 every time a new image is uploaded) someone can easily start at 0 and just try every possible image id. If you've done what I suggested earlier, they won't get access to images they shouldn't see, but you can't stop them from harvesting all of the images they can see. To stop that from happening you want to make the image id's non-sequential. You can either use very long random numbers, or the SHA1 hash of the image contents. The advantage of SHA1 is that theres 2^256 possible SHA1 hashes, and only a very small number of those will be used within your system. The ones that are used will be distributed at random amongst all of the possible vales. So if someone started at 0 and tried all of the possible SHA1 hashes, it could take a very long time for them to find one that's actually in use. Of course it won't stop them from hammering your server trying, but it does effectively prevent them from harvesting all of the images.

Hope that helps.

Jim.

El Forum

[eluser]alpar[/eluser]
The way i do it is use a .htaccess file to prevent access from the images folder. Make a php file to pull images, and check if user has access and serve.

El Forum

[eluser]crikey[/eluser]
Thank you for all who posted a suggestion to help me out here.

@Jim: the idea of storing the images outside of the web root seems pretty obvious actually, and might work for my purposes. I'm not worried about people harvesting images that are "public" (ie that anyone can see). The point is mainly to keep "private" flagged images from being accessed by anyone other than the user that uploaded them.

I guess it raises the issue though of serving the public/private images as part of an HTML page (in this case the image content itself wouldn't be output, rather a link to it, as in
Code:
<img src=... />
This is what would happen when displaying search results (which would show some data for each item and an image thumbnail).

Maybe this is where rogierb's solution might be more applicable?

Thanks again for your contributions.