Question

I am trying to block hotlinking of my Cloudfront files from specific domains. Through a combination of online examples and Amazon's own policy generator, I have come up with this:

{
  "Version": "2008-10-17",
  "Id": "http referer policy",
  "Statement": [{
    "Sid": "Block image requests",
    "Action": "s3:GetObject",
    "Effect": "Deny",
    "Resource": "arn:aws:s3:::mybucket/subdir/*",
    "Condition": {
      "StringLike": {
        "aws:Referer": [
          "http://example.com/*"
        ]
      }
    },
    "Principal": {
      "AWS": "*"
    }
  }]
}

I sent an invalidation request for a file in the subdirectory of mybucket, then a few minutes later tried reloading the image with the referer header still sent (verified using Chrome's dev tools). Did a hard reload with Ctrl+F5, and the response headers contained "X-Cache:Miss from cloudfront" so it's definitely getting the latest version of the image.

But the image is still displaying fine and is not blocked. The policy generator did not have an option for the "aws:Referer" key, but it's in the Amazon docs here. Have I done something wrong here?

Was it helpful?

Solution

Update 2

Revisiting your policy I wonder how you have actually allowed CloudFront access to your objects in the first place? Have you by chance followed the common advise in e.g. Start Using CloudFront with Amazon S3 that You must ensure that your object permissions are set to Make Everything Public for each object in your Amazon S3 bucket.

In this case you might have stumbled over a related pitfall due to the interaction between the meanwhile three different S3 access control mechanisms available, which can be rather confusing indeed. This is addressed e.g. in Using ACLs and Bucket Policies Together:

When you have ACLs and bucket policies assigned to buckets, Amazon S3 evaluates the existing Amazon S3 ACLs as well as the bucket policy when determining an account’s access permissions to an Amazon S3 resource. If an account has access to resources that an ACL or policy specifies, they are able to access the requested resource.

Consequently you would need to migrate your ACL to the bucket policy (i.e. allow CloudFront access before denying via aws:referer) and delete the overly generous ACL thereafter.

Good luck!


Update 1

Okay, now with client caching out the way, I'm afraid this is going to be non trivial (as apparent when you search for aws:referer in the AWS forums), thus might require a couple of iterations (especially given you have researched the topic yourself already):

  • The most common issue encountered is the leading whitespace error in the AWS documentation (which is particularly annoying, because a simple documentation fix would remedy lots of wasted time on behalf of users and AWS support staff alike)
    • Your policy doesn't exhibit this issue, however, given you sanitized the real domain you might have replaced the error in your production code in fact?
  • Also it is important to realize that the HTTP referer header is not necessarily going to be available, see e.g. Referer Hiding (thus your policy won't prevent malicious access anyway, though that's apparently not the issue)
    • You stated already, that you have verified it to be sent via the Chrome developer tools, so this doesn't apply either (I'm mentioning it to stress the reduced security level).

The policy looks fine at first sight - before digging further into this direction though, I'd recommend to ensure that you are actually bypassing Chrome's cache successfully, which is notoriously less straight forward than people are used to from other browsers; in particular, Ctrl + F5 simply reloads the page, but does not Bypass the cache (not reliable at least)!

As documented there as well, you could use one of the other key combinations To reload a page and bypass the cache (including the confusing 2nd Ctrl + F5 after the 1st one reloaded) , however, I recommend facilitating one of the following two alternatives instead:

  • Chrome's developer tools offers dedicated support for browsing without a cache - in the bottom right corner of the toolbox panel is a cog icon for settings, clicking this triggers an overlay with an options panel, amongst these you'll find the option Disable cache under section Network.
  • Chrome's Incognito mode (Ctrl + Shift + N) keeps Google Chrome from storing information about the websites you've visited, which as of today (might change anytime of course) seems to include cached content, cookies, DNS and the like as expected, thus is an even quicker, though less explicit option right now.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top