How to protect against direct access to images? [closed]
Asked Answered
I

10

28

I would like to create a web site with many images. But I would like to protect against direct access to images, e.g. direct links to images without visiting the web site.

What is the preferred way to do this? And what are the alternatives with Pros and cons?

I have some ideas (I don't know if they are possible):

  • File permissions
  • PHP Sessions
  • Temporary file names or URLs
  • HTTP Redirection?

Maybe this isn't practiced on many web sites? E.g. I tried to access a private photo on Facebook without beeing logged in, but I could still visit the photo.

The platform will probably be a Ubuntu machine with NginX and PHP.

Isagogics answered 21/10, 2010 at 17:44 Comment(6)
You're able to access the "private" photo on Facebook because you were using the direct image link, rather than the photo page.Forefoot
@jnpcl: Yes, that is what I would like to prevent on my site. The question is how to do it?Isagogics
Are you trying to prevent hotlinking, or something more? #1246369Sinistrocular
@Greg: Yes, but I can not use that method since I'm using Nginx and I don't have .htaccess files.Isagogics
What are you trying to prevent? Just hotlinking, or do you want user/membership based access permissions?Matchmaker
@CodeInChaos: I'm interested in solutions for both cases.Isagogics
K
24

https://www.php.net/image

You link the img element to a php file. This file checks if the user has the right permission, if so it can send an img response back.

<img src="url/LoadImg.php?id=1337" alt="" />

Still someone with the permission can download the image and provide it to other people somewhere else (webspace/mail/whatever). To make it a bit harder to steal it you can disable right clicking on the image, but still a user who knows a little bit about http should not have any problems to steal it. You can place a signature over the image (for example the logo/name of your website) so people can see that you where the source. This can be done with php aswell.

If you want to be funy you can setup an other image that is sent if the link comes from an other page :P

Khmer answered 21/10, 2010 at 17:52 Comment(3)
I have been using this method on my site but when there are many photos on the page, the time to display the page is really long (each photo has an access check done and a server request...). Does anyone have an idea of what could be done to alleviate that issue?Amerson
Same problem here. It loads very slow and I cannot work with Lazy. Is there an other way?Apogamy
use Nginx, valid_referers *.yourdomain.com yourdomain.com; if ($invalid_referer){ return 403; }Bacteriology
F
18

Add a simple .htaccess file in your site folder with the follwoing lines

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://www\.your-domain\.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http://www\.your-domain\.com$ [NC]
RewriteRule .*\.(wav|swf|jpg|jpeg|gif|png|bmp|js|css)$ - [F,NC,L]

Note I added also js and css file even if I think it's bizzare to find someone who attempts to scrape them.

Faradism answered 1/12, 2012 at 12:38 Comment(4)
is this code will block direct access and cross-website access to css, js, txt and image files?. only my website can use my assets and none other?. Does this give 403 error to them?Buttocks
@shanmugapradeep Yes, yes and yes. However, you should note that the HTTP Referer is unreliable. By blocking an empty Referer header (ie. "direct access") you might also block legitimate users as an increasing number of users (and browsers) choose to suppress the Referer header entirely these days in interests of user privacy.Cess
@Cess Then how can we only block cross-domain linking to our assets for protection of assets and also server resourcesButtocks
this answer is legendary ,simple and works perfectlyGalloway
I
10

You can dynamically protect a folder using htaccess and the users ip.

Add a .htaccess file to your images folder with the following lines:

order deny,allow
deny from all

Then use PHP to insert the users ip into the htaccess file when they log in like this:

<?
$ip = $_SERVER['REMOTE_ADDR'];
if (!filter_var($ip, FILTER_VALIDATE_IP)) exit();
$file = $_SERVER["DOCUMENT_ROOT"].'/YOUR_IMAGE_FOLDER/.htaccess';
$current = file_get_contents($file);
$current .= "allow from ".$_SERVER['REMOTE_ADDR']." #".$_SESSION['id']."\n";
file_put_contents($file, $current);
?>

The folder will be blocked from any ip that is not logged in.

Notice that I checked to see if the ip is valid. It is important that you give the user no way to inject their own code into your htaccess file.

Also notice that I put the users id in a comment to the right of the ip in the htaccess file. When the user logs out you can search the htaccess file and remove the ip of the user.

You can update this on every request to prevent users who are using dynamic ips from getting kicked off.

I use this method with my entire members areas, it is an excellent added layer of security. Just make sure that you put your log in scripts outside of the members folder.

Irritated answered 16/9, 2014 at 21:2 Comment(2)
What a beautiful answer. CheersMazur
How do you remove the line from htaccess that has the comment beside it?Saharan
F
3

This might be useful: Allow/deny image hotlinking with .htaccess

Edit: One thing to note about this method is that some Browser/AV/Firewall software removes Referer data when you browse, which would cause potentially legitimate users to be treated as hotlinkers.

If your site already uses some kind of authentication or session system, then it would be better to use the method given in @Mark Baijens' answer.

Update: NGiNX rewrite rule to prevent hotlinking:

location ~* (\.jpg|\.png|\.css)$ {
    valid_referers blocked mydomain.com www.mydomain.com;
    if ($invalid_referer) {
        return 444;
    }
}
Forefoot answered 21/10, 2010 at 17:53 Comment(5)
Thanks, however I can not use that method since I am using NingX as webserver and don't have any .htaccess files.Isagogics
With some tweaking, it's possible.Forefoot
Thanks, I will have a look at that solution.Isagogics
And those programs don't only remove the referrer, they sometimes replace it with some constant string. So you probably need a longer whitelist of valid referrers.Matchmaker
@Jonas: your webhoster does not let you add an .htaccess file?! CHANGE WEBHOSTER!Faradism
T
3

You could use a PHP script to retrieve the images using something like:

<img src="mysite.com/getimage.php?id=001" />

and have the PHP script return the image data only after confirming that the domain of the HTTP_REFERER is your's.

If you have an account-oriented site, I suggest using PHP sessions as you stated and have the PHP script verify the session before returning the image data.

Tangelatangelo answered 21/10, 2010 at 17:54 Comment(1)
Would be great to have more details (or a link) explaining "the domain of the HTTP_REFERER".Floreated
D
2

I use both methods - checking user gent and and referrer. User agent I check at .htaccess. And referrer check at php file. You can see it at http://coloring-4kids.com

Here is my code:

RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?pinterest\.com/.*$ [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?pinterest\.com$ [NC]

RewriteCond %{HTTP_USER_AGENT} !(Googlebot|bingbot|msnbot|yahoo-mmcrawler|YandexImages) [NC]
RewriteCond %{HTTP_USER_AGENT} !googlebot-image [NC]
RewriteCond %{HTTP_USER_AGENT} !googlebot [NC]
RewriteCond %{HTTP_USER_AGENT} !googlebot-news [NC]
RewriteCond %{HTTP_USER_AGENT} !googlebot-video [NC]
RewriteCond %{HTTP_USER_AGENT} !googlebot-mobile [NC]
RewriteCond %{HTTP_USER_AGENT} !mediapartners-google [NC]
RewriteCond %{HTTP_USER_AGENT} !mediapartners [NC]
# RewriteCond %{HTTP_USER_AGENT} !adsbot-google [NC]
RewriteCond %{HTTP_USER_AGENT} !bingbot [NC]
RewriteCond %{HTTP_USER_AGENT} !facebookexternalhit [NC]
RewriteCond %{HTTP_USER_AGENT} !baiduspider [NC]
RewriteCond %{HTTP_USER_AGENT} !yandex [NC]
RewriteCond %{HTTP_USER_AGENT} !sogou [NC]
RewriteCond %{HTTP_USER_AGENT} !twitterbot [NC]
RewriteCond %{HTTP_USER_AGENT} !pinterest [NC]


RewriteRule (^.*\.(gif)$) /watermark.php?src=$1 [L]

watermark.php

<?php  

$test = getenv("HTTP_REFERER");
$proverka =  substr($test, 0, 25);

 header('content-type: image/jpeg');

 $image = imagecreatefromgif($_GET['src']);

 $watermark = imagecreatefromgif('watermark.gif');

 $watermark_width = imagesx($watermark);
 $watermark_height = imagesy($watermark);


 $dest_x = imagesx($image) - $watermark_width;
 $dest_y = imagesy($image) - $watermark_height;



if (strpos($proverka, 'media') !== false)
   { $pinproverka=true; }

 if (($proverka != 'http://coloring-4kids.com') && (imagesx($image) > 400) && ($pinproverka!=true) )  { imagecopymerge($image, $watermark, $dest_x - 5, 5, 0, 0, $watermark_width, $watermark_height, 100); }



 imagegif($image);

 imagedestroy($image);
 imagedestroy($watermark);

?>
Drifter answered 18/3, 2014 at 9:38 Comment(0)
G
1

This is going to be hard to do. In order for your clients' web browsers to access the pictures, they need to be readable. File permissions won't work because you'll need to grant access to the browser. You won't be able to stop someone from downloading them and doing something with them.

If you only want to stop direct linking, if you change the filenames on a regular basis and update your pages to reflect this, other pages will have their links broken.

Gaziantep answered 21/10, 2010 at 17:53 Comment(1)
Good point changing the filenames, never thought about that. Sure it doesn't deny downloading or accessing at least once (brute-force), but at least shuffles up the cards wiping malicious progresses.Holystone
H
1

There are perfomance issues on above answers. My solution is to login system is follows.

You can rename the directory of images every hour / day etc.

images/2h4h4h4h4282hdj/182828.png to something like images/dhd777rhrje82883/182828.png

You can do this to complete system or to the specific user.

Hackamore answered 18/2, 2020 at 3:55 Comment(0)
J
0

Add Deny Rule in your .htaccess

RewriteEngine on 
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain\.ltd [NC] 
RewriteCond %{HTTP_REFERER} !^http://(www\.)?domain\.ltd.*$ [NC] 
RewriteRule \.(gif|jpg|js|txt)$ /messageforcurious [L]
Jarl answered 6/12, 2016 at 10:55 Comment(0)
I
0

Apache

httpd.conf

<Directory "/var/www/html/img">
    AllowOverride None
    order deny,allow
    Options FollowSymLinks
</Directory>
Isabel answered 18/7, 2021 at 19:37 Comment(1)
<Directory "/var/www/html/img"> AllowOverride None order deny,allow Options FollowSymLinks </Directory>Isabel

© 2022 - 2024 — McMap. All rights reserved.