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:
https://s3.eu-central-1.amazonaws.com/mybucket/myfile.jpg

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!