Prevent hot-linking of generated thumbnails? - .htaccess

I have a .htaccess file that contains directives to prevent the hot-linking of static assets (images, CSS and JavaScript files). The relavant code looks like this:
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?ipwuk.com/.*$ [NC]
RewriteRule \.(gif|jpg|js|css|png)$ - [F,L]
This is great and does the job; however, I have a PHP script that automatically generates thumbnails (and doesn't contain the file extension in the URL). A sample thumbnail URL looks like this:
http://example.com/inc/image.php/4e7efde2ee8ac.jpg/610/343/fill
Or:
http://example.com/inc/image.php/[seed].[extension]/[width]/[height]/[thumb type]
How can I prevent images generated by the above script from being hot-linked (which I suspect my client is doing and as a result is eating bandwidth to the tune of over 150MB a day)?

This code denies all requests for image.php that are NOT direct or from specified website.
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?ipwuk\.com/.*$ [NC]
RewriteCond %{REQUEST_URI} ^/image.php(.*)$ [NC]
RewriteRule ^(.*)$ - [F,L]

Could you not actually prevent - EDIT: discourage - it in the script that generates the thumbnail itself?
In pseudo-PHP:
if (parse_url($_SERVER['HTTP_REFERER']) != "yourSite"){
//generate thumbnail that says "don't hotlink, scum!"
}
else {
//do your normal thumbnail generation routine
}

Related

.htaccess allow hotlinking of images with parameter (?something)

I have code in my .htaccess file to prevent hot-linking of images on my site.
What I need is to make it allow hot-linking of images it they have some parameter at the end of URL, for example:
This image should be blocked:
https://my-site.com/my-images/some-image-file-name.jpg
BUT, ALLOW hot-linking if that same image have parameter at the end, for example:
https://my-site.com/my-images/some-image-file-name.jpg?allow_hot_linking
WHY I NEED SOMETHING LIKE THIS?
For example, if image is sent inside html email, it will not be displayed, but if I could make some .htaccess rule which would allow hot-linking of images with parameter I will simply put that parameter at the end of img source tag of image while making html email and it will appear when email is opened.
This is my .htaccess code
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?my-site.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?nnn.nnn.nn.nnn [NC]
##Allow search engines
RewriteCond %{HTTP_USER_AGENT} !Googlebot-Image [NC]
.
.
.
##Allow blank referrers
RewriteCond %{HTTP_REFERER} !^$
## Redirect to hotlink image
RewriteRule ^my-images/(.*).(jpeg|jpg|bmp)$ https://my-site.com/no-hotlinking.html [NC,R,L]
## End - prevent image hotlinking
Love this solution, exactly what I was looking for to allow links from emails but not from blank referrers.
RewriteCond %{QUERY_STRING} !^ahl$ [NC]
Works a dream.

Hotlink protection excluding a particular URL

We have tried adding the below hotlink protection inorder to save the bandwidth.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
This is working perfectly. Now, we want to exclude hotlink protection for the URL admin/thumbs (domain.tld/admin/thumbs/image.jpg) should be excluded from the hotlink protection.
We tried adding the below code however its not working. We searched on stackoverflow and multiple forums however none were helped us.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteCond %{REQUEST_URI} !/admin/thumbs$
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
Any help would be appreciated.
RewriteCond %{REQUEST_URI} !/admin/thumbs$
This creates an exception for any URL that ends with /admin/thumbs, whereas it would seem you want to create an exception for any file in the /admin/thumbs subirectory, ie. any URL that starts /admin/thumbs.
The suggestion !^admin/thumbs/? in comments is incorrect, since the REQUEST_URI server variable always starts with a slash so the condition will always be successful and the request is potentially blocked.
You should use the CondPattern !^/admin/thumbs($|/) instead to exclude requests for /admin/thumbs, /admin/thumbs/ and /admin/thumbs/<anything>, but not /admin/thumbsomething. For example:
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
Your existing rule can be further simplified/refined since the existing conditions that check the HTTP_REFERER are "the same", but also match too much. And the mixed case RewriteRule pattern can be flattened by using the NC (nocase) flag instead.
For example, the complete rule would become:
# Hotlink protection for images, except those in "/admin/thumbs/..."
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com($|/) [NC]
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
RewriteRule \.(gif|jpg|png|jpeg|mp4|mkv|webm|ico)$ - [NC,F]
Note that this also blocks an empty Referer header. This includes direct requests (anyone typing the URL directly into the browser's address bar) and any user that has suppressed the Referer in their browser (which some users do for increased privacy).
Alternative solution with additional .htaccess file
Alternatively, you could create an additional .htaccess in the /admin/thumbs/ subdirectory and simply disable the rewrite engine. For example:
RewriteEngine Off
This overrides and prevents the hotlink-protection directives in the parent config from being processed when anything within this subdirectory is requested.

Display particular (dynamicaly) URL without parent folder. Leave The Others Alone

I started learning rewrites today
First of all here are examples of my links
Index.php?action=pictures
Index.php?action=pictures&type=kitchen
Index.php?action=pictures&type=ceiling
Index.php?action=services
Index.php?action=services&type=shower
Index.php?action=services&type=windows
In my .htaccess file I have this
RewriteEngine On
RewriteBase /
#Do not Rewrite files or folders
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule ^(.*?)$ $1 [L]
#Ordinary
RewriteRule ^\.htaccess$ .htaccess [F]
RewriteRule ^(.*)/(.*)/?$ Index.php?action=$1&type=$2 [L]
RewriteRule ^(.*)/?$ Index.php?action=$1 [L]
Rewrites URLs to
localhost/pictures
localhost/pictures/kitchen
localhost/pictures/ceiling
localhost/services
localhost/services/shower
localhost/services/windows
//etc
I like to have ALL my links working as is with an exception of services where I don't need parent folder /services/.
Result:
localhost/pictures
localhost/pictures/kitchen
localhost/pictures/ceiling
localhost/services
localhost/shower
localhost/window
I tried to rewrite .htaccess but either I get only parentfolder to work or only subfolder.
I tried to add this but I do understand that this matches everything...
RewriteRule ^(.*)/?$ Index.php?action=services&type=$1 [L]
I can however hardcode it like this
RewriteRule ^window/?$ Index.php?action=services&type=window [L]
Would like to have something dynamical. If folder services -> show no folder yet still be able to see localhost/services!
Is it possible?
Think of it this way: How would Apache know if a particular string is an action, or a type of service?
Well, you have three options:
We hardcode the types of services. Anything that does not match a type must be an action.
We hardcode the actions. Anything that does not match an action must thus be a type of service.
Apache has no way of knowing: We feed it to a script, who might be able to do some magic to find out what this string is.
In your case hardcoding the actions seems like the best idea, at least when the actions are static.
RewriteRule ^(.*)/(.*)/?$ Index.php?action=$1&type=$2 [L]
RewriteRule ^(pictures|services)/?$ Index.php?action=$1 [L]
RewriteRule ^(.*)/?$ Index.php?action=services&type=$1 [L]

htaccess codes did not work

This is EXACTLY the same case as: (htaccess) How to prevent a file from DIRECT URL ACCESS?
But, no one of codes provided by answers work for me. I tried 1 by 1, then tried to combine, but still not works. Here is my code:
# prevent direct image url access
# ----------
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com.*$ [NC]
# this not works
RewriteRule \.(png|gif|jpe?g)$ - [F]
# and this
RewriteRule \.(png|gif|jpe?g)$ - [F,NC]
# and this
RewriteRule \.(png|gif|jpe?g)$ https://example.com/wp-login.php [NC,R,L]
# even by combining them
# ----------
# /prevent direct image url access
The case simulation:
index.php has <img src="test.png" alt=""> and should be normally accessible. The requirement is: http://example.com/test.png shouldn't be accessible.
I use WordPress in wp-engine, and i think WordPres's default rewrite doesn't cause the problem since the code from answers are placed above WordPress rewrite.
UPDATE
I use PHP Version 5.5.9-1ubuntu4.14 on Apache 2 on wp engine
Your rules basically work for me, except for one thing:
The (s) is not doing what you think it does.
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com [NC]
With parentheses you define a group, which doesn't make any sense at this point. If you remove the (s), it works for http.
If you want to use https too you have to write it like this:
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
The ? will make the preceding character (or group, if in parentheses) optional.

allow image access only from specific html page

I've got different users for my website, owning different images which are all stored in the same folder. The images are stored in an incremental fashion, 1.jpg, 2.jpg etc.
User can view these pictures on a specific php page. Now I want to restrict the access to these images only through this php page so that they can't simply enumerate all the filenames to see the images of other users.
I thought of doing this with an .htaccess file which is stored besides the images in /shop/img/userimg/ and would look something like this:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/shop/shop.php [NC]
RewriteRule .*\.(jpe?g|gif|bmp|png)$ - [F]
My site is a subsite (as you can see: /shop/) and the php page to view these images would be shop.php.
Now, is this possible at all? What am I doing wrong?
Note that the referer header is not to be trusted. Some proxies and firewall remove the header entirely, so you have to account for it not being present (that's what the 2nd line is for)
RewriteCond %{HTTP_REFERER} !/shop/shop\.php$ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule \.(jpe?g|gif|bmp|png)$ - [F,L]
Try adding the following to your htaccess file.
RewriteEngine On
RewriteBase /
#if the referer (page request came from) does not contain shop.php
RewriteCond %{HTTP_REFERER} !/shop/shop\.php [NC]
#and it is a request for images, then send a 403 forbidden
RewriteRule \.(jpe?g|gif|bmp|png)$ - [F,L]

Resources