Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to restrict AWS S3 access using CORS?

How do I set up CORS on Amazon S3 to allow only approved domains to access a JS script in my S3 bucket? Currently, I have CORS set as follows on my S3 bucket:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>www.someapproveddomain.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Yet any domain can access and run script hello.js (which resides in the S3 bucket) as demonstrated at JSFiddle. Does anyone what I'm doing wrong? Or, maybe I'm just misunderstanding what CORS is supposed to do?

like image 452
Bob Arlof Avatar asked Jan 06 '23 16:01

Bob Arlof


2 Answers

Instead of trying to solve this with CORS, you need to solve it using an S3 Bucket Policy that restricts access to a specific HTTP referrer. This is documented here.

This is the example bucket policy given by AWS:

{
  "Version":"2012-10-17",
  "Id":"http referer policy example",
  "Statement":[
    {
      "Sid":"Allow get requests originating from www.example.com and example.com.",
      "Effect":"Allow",
      "Principal":"*",
      "Action":"s3:GetObject",
      "Resource":"arn:aws:s3:::examplebucket/*",
      "Condition":{
        "StringLike":{"aws:Referer":["http://www.example.com/*","http://example.com/*"]}
      }
    }
  ]
}

Note that the HTTP referrer is fairly easy for an attacker to spoof.

like image 136
Mark B Avatar answered Jan 08 '23 08:01

Mark B


I do think you're misunderstanding CORS. (Edit: which is okay!)

CORS isn't intended for server-side security.

There are much better explanations here on SO than what I can explain, but one of the main purposes of this is to prevent someone from creating a fake site (like a banking portal) and having it make requests to the real server with the user's real credentials. If the server and real site have CORS enabled, the server will only allow requests from the real site's domain.

What you probably want to look into is using IAM policies or S3 bucket policies. There's an excellent blog post from AWS here that goes over this. You'll need to have an EC2 instance as a sort of middle-man to access the S3 bucket and server the files to a client.

There may be another way to do this with purely S3, but essentially if its accessible publicly without authentication, someone can technically spoof the headers to make it appear like its coming from your CORS defined domain.

like image 41
Lucas Watson Avatar answered Jan 08 '23 06:01

Lucas Watson