0

I have a simple upload/retrieval script to retrieve imaged from my database. When I upload files the script stores them in upoadsFolder/. Ihen I want to display retrieve images I use the following code:

<?php

include('./dbconn.php');
$q=$dbconnection->query('SELECT * FROM img_table WHERE id=7');
$row=$q->fetch();
$row['imgpath'];

echo "<img src=uploadsFolder/$row['imgpath'] />";

But if the user knows or can predict any of my images names, e.g nameX.png he will easily view these images by modifying the HTML <img> tag: <img src=uploadsFolder/nameX.png />.

How can I protect uploadsFolder/ to prevent this?

MOREOVER : The user also will be able to view whole content of my ' 'uploadsFolder/' contents if Only he typed in his/here browser the URL: " localhost/uploadimages/uploads/ " !!! See the attached !

enter image description here

Mvrk
  • 225
  • 2
  • 13
  • You want to not allow anyone Use your web server resources.With an image URL Address??? – pedram shabani Sep 05 '17 at 12:26
  • No.I just want to prevent any access to the other img/files in [UploadsFolder] – Mvrk Sep 05 '17 at 12:28
  • You can change the name of the photo.In a period of time.or after each visit to the photo.Of course, after changing the name of the photo every time You must update **img_table** table – pedram shabani Sep 05 '17 at 13:00
  • @Mvrk about folder contents, please take a look at https://stackoverflow.com/q/2530372/3136474 – Dinei Sep 05 '17 at 16:48

4 Answers4

2

Doing the following will solve your issue:

  • Store the image files somewhere obscure, such as a directory folder structure in your public_html area. On the parent folder of this you can prevent hotlinking with htaccess, and simply deny all access to the files. (It's more secure storing within rather than outside of the public html area).

     # htaccess full file:
     Options -Indexes
     Deny from all 
    
  • Use a PHP file to reference the image you want to show; such as :

    echo "<img src='uploadsFolder/showImage.php?img=".$row['imghash']."' />";
    
  • The PHP file referenced above - "showImage.php" - can then search the database for this unique hash column. Once found, the PHP file then uses file_get_contents() to load the image and then output this image to the <img> link with the appropriate headers.

  • Add the hash column to your existing data and populate it (generate random strings). Ensure it is indexed as unique.

Outcome

The image files should not be stored in the same folder as the PHP image display file. This folder will not only contain your PHP file. Obviously for ease you can change the location of this folder (example: /imageToucher/showImage.php?img=".$row['imghash'].", etc.) or you can update your image filepaths in your MySQL with a quick universal find and replace.

Now every time you want to load any protected file; you simply call the PHP file, and let it do the work of checking the database for the hash, getting the associated file path, grabbing the file from that path, loading it, parsing it and then outputting it as the output of the PHP file itself.

Bonus to this method

  • Your filepath of your sources are never ever revealed.
  • You can quickly throttle (delay) people who try to find files that do not exist, with a sleep() statement in PHP, so people who cycle through different $_GET['img'] values will quickly get slowed down (you can use sessions or IP trackers or similar to keep count of failed attempts at loading image URLs)
  • The PHP file can manipulate any valid image found, so you can show images just as thumbnail sizes, or set other output criteria as you need.

A minor downside could be this data in this folder will need to be parsed by code in another part of the website to be displayed because the .htaccess wil deny all direct accesses, this includes references in webpages, so access has to be via PHP and the database to collect the valid URLs. This can make thumbnail listings etc. much more processor heavy and less efficient in busy scenarios.

Martin
  • 22,212
  • 11
  • 70
  • 132
  • Wow, Thank you for this well written explanation. I wil get bak to you after i try this . – Mvrk Sep 06 '17 at 10:33
1

"MOREOVER : The user also will be able to view whole content of my ' 'uploadsFolder/' contents if Only he typed in his/here browser the URL: " localhost/uploadimages/uploads/ " !!! See the attached !"

If you don't want this to happen then you should create an .htaccess file on your site and have the following in it:

RewriteEngine on

<ifModule mod_rewrite.c>

Options -Indexes

</IfModule>

This restricts access to any folder on your site without the full link to the document/file/image, etc., they'll get a 403 Forbidden error message.

Just save the file as .htaccess

Also instead of saving the image in the database, just save the filename and then upload the image to the uploads folder and then have something like:
<img src="uploads/<?php echo $row['image_name']; ?>"> that way if the user gets access to your DB (that'd be your fault btw), all they'd have access to is the file name and not the actual image.

You could also try what @heXer said. Create a system where only if the user is logged in, they and only they can view the image else show an error message or redirect them to another page.

JeanPaul98
  • 492
  • 6
  • 18
  • YEs i see ., the are alot of work must be done in htaccess to make your app secure as much as you can , i guess i need to read some htaccess write mod tutorials . – Mvrk Sep 06 '17 at 10:35
0

Since you want to display them, you need to have them somewhere public. However, you can store them in DB using a hash (md5 of id+timestamp). This way, the name can't be predicted. Basically the only way is to make it unpredictable. You could save them as an md5(id), but that would still make them a bit predictable if someone learns of the algorithm.

heXer
  • 304
  • 1
  • 10
  • Thank you , I'm already did that i store images after i rename theme by using very complex names unique and non-sequential names . but still that is not enough . – Mvrk Sep 05 '17 at 12:23
  • If you have a login (user/pass) system, you could make a php script that would output the image only if the user is logged in. This would allow you to move the images outside of the public folder. – heXer Sep 05 '17 at 12:49
  • 1
    Also, if it's a complex name, you are already there. Not even Facebook can hide images. For example log yourself in FB, view source of a private image, copy the URL, and open the URL in another browser. You'll see you can view it. It's not possible to prohibit access to something if you want to be able to show it, without having another type of chek (e.g. you are logged in). Think of what type of things you could check and do it (e.g. I want to show this image only to someone who XXXX - once you have the XXX condition, let us know). – heXer Sep 05 '17 at 12:52
  • MOREOVER : The user also will be able to view whole content of my ' 'uploadsFolder/' contents if Only he typed in his/here browser the URL: " localhost/uploadimages/uploads/ " !!! See the attached img : imgur.com/a/pw0Oe – Mvrk Sep 05 '17 at 13:41
  • To fix that you have to disable Index Listing via vhost OR .htaccess: write this in a htaccess file inside that folder "Options -Indexes" – heXer Sep 16 '17 at 19:03
0

If the user can do a directory listing, you obviously lost already.

Generally, relying on secret names and/or links rather than implementing access control is bad practice. These secrets tend to leak in all sorts of ways. For example, have a look at what happened to DropBox.

Another way that security often fails when people attempt things like this is using predictable randomness rather than cryptographic randomness to derive secrets. The PHP Mersenne Twister random number generator is predictable: knowing a few outputs (i.e. from an image that a user is allowed to know) would allow the user to derive future outputs (future image links) and previous (image links that are already there). The same is true with PHP's lcg_value.

Bottom line: there is no substitute for proper access control. Otherwise, you are violating the complete mediation security principle, which makes you vulnerable to direct object reference vulnerabilities.

TheGreatContini
  • 6,429
  • 2
  • 27
  • 37