Miguel David |||

How to deny hot linking from your AWS S3 files

There are many good people in the web, but there are also those who are lazy and instead of creating content themselves or even hosting it, they will want to abuse the existing stuff online. For example, say you have a bucket (originally) called mybucket and a file called … myfile.jpg. You uploaded the file to AWS S3 and now you are serving it from there through a webpage that we’ll call test.html.
Here’s what the URL of the file could look like:

And your test page could be like:

<html><body><br> Hello<br> <img
src=”https://s3.eu-central-1.amazonaws.com/mybucket/myfile.jpg" alt=”” /><br>
</body></html>

Now Mr. Evil comes along and likes your myfile.jpg but does not want to pay for the bandwidth for when someone goes into his website to see your myfile.jpg. How does he do it? Simply:

<html><body><br> Mr. Evil’s webpage<br> <img
src=”https://s3.eu-central-1.amazonaws.com/mybucket/myfile.jpg" alt=”” /><br>
</body></html>

Every time someone visits his page, not only are they seeing your file but the bandwidth charges are coming to you because they are in effect accessing the file in your AWS account!

How to prevent this? Using a bucket policy. Go to S3 in your account, then click on your bucket, then click on Permissions and Edit bucket policy. You will see an empty text box. Copy paste the code below and adjust to your bucket name and your website URLs:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mybucket/*"
        },
        {
            "Sid": "Deny requests for hot-linking.",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::mybucket/*",
            "Condition": {
                "StringNotLike": {
                    "aws:Referer": [
                        "http://*.mywebsite.com/*",
                        "https://*.mywebsite.com/*"
                    ]
                }
            }
        }
    ]
}

NOTE: If you have Cloudfront in front of your S3 bucket, then other rules apply. I’ll cover that in another post.

What is happening here is that in the first statement we are allowing everyone to get our files in this bucket (required for web access to the world), but then in the second statement we are saying that S3 should only allow the objects to be available if the referral is a variation of mywebsite.com (in this case with and without www and https).

What happens now? When anyone visits your test page they will be able to see the file, but when they go to Mr. Evil’s page they will see a broken link where the image should be. :)

Take that Mr. Evil!

Up next S3/Cloudfront Access Denied So you finally listened the SEO guys who keep saying that the images on your website have to be fast and you decided to move them from your small New blog, new life Welcome! This blog has had several iterations over the years. Most of its life was in a self hosted WordPress, a bit in Anchor, a bit in Ghost and
Latest posts Today I learned about view My git flow Using multiple versions of kubectl on macOS Merging two MySQL (or MySQL compatible) databases in AWS using DMS Inspired Recommendations for Portugal God is dead (and we are suffering from it) Advice to my unborn child: be a plumber and an artist On light and shadow You can usually do more/better than you think you can Upkeep Comparing myself to others Fear, Procrastination. Procrastination, Fear Liberalism and a new system Chores Finding my calm place Turning 38 Privilege Humbling Habits Frustration The miracle of the blank page On being late Love is the base of it all A letter to my dead grandfather Self imposed stress Rent the world Start at 6:30 How to get multiple domains pointing to GitHub Pages using Cloudflare My MySQL Cookbook How to make Jekyll multilingual