简体   繁体   中英

copyObject Access Denied on S3 Bucket despite policy allowing my site referrer

I am using AWS SDK for PHP to upload and display files to/from my S3 bucket.

The files should only be accessible through my site, no other referrer allowed - no hotlinking etc.

I also need to be able to copy objects within the bucket.

I create and connect as normal:

    $s3Client = new Aws\S3\S3Client([
        'version'       => 'latest',
        'region'        => 'eu-west-2'
    ]);

    $s3 = $s3Client::factory(array(
        'version'       => 'latest',
        'region'        => 'eu-west-2',
        'credentials'   => array(
        'provider'      => $provider,
        'key'           => $key,
        'secret'        => $secret
        )
    ));

And execute Copy object command:

    $s3->copyObject([
        'Bucket'     => "{$targetBucket}",
        'Key'        => "{$targetKeyname}",
        'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
    ]);

I have tried a policy using "Allow if string like referrer" but AWS then tells me I'm allowing public access?!?!? Everything works just fine EVEN the copyObject action but files are still accessible directly and from everywhere!

I try using "Deny if string not like referrer" which works mostly as expected - I can upload and display the files and the files don't show when linked directly (which is what i want) - However, the copyObject action no longer works and i get the access denied error.

I've tried everything else i can think of and spent hours googling and searching for answers but to no avail.

Here's each seperate policy...

ALLOW FILE ACCESS ONLY (GetObject) if string LIKE referrer:

{
"Version": "2008-10-17",
"Id": "",
"Statement": [
    {
        "Sid": "Deny access if referer is not my site",
        "Effect": "Deny",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": [
            "arn:aws:s3:::MY-BUCKET/*"
        ],
        "Condition": {
            "StringLike": {
                "aws:Referer": [
                    "http://MY-SITE/*",
                    "https://MY-SITE/*"
                    ]
                }
            }
        }
    ]
}

RESULT: uploads & copyObject work but files are still accessible everywhere


DENY ALL ACTIONS (*) if string NOT LIKE referrer:

{
"Version": "2008-10-17",
"Id": "",
"Statement": [
    {
        "Sid": "Deny access if referer is not my site",
        "Effect": "Deny",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": [
            "arn:aws:s3:::MY-BUCKET/*"
        ],
        "Condition": {
            "StringNotLike": {
                "aws:Referer": [
                    "http://MY-SITE/*",
                    "https://MY-SITE/*"
                    ]
                }
            }
        }
    ]
}

RESULT: copyObject action no longer works and i get the access denied error

AWS is probably warning you that it's public because it is, for all practical purposes, still public.

Warning

This key should be used carefully: aws:referer allows Amazon S3 bucket owners to help prevent their content from being served up by unauthorized third-party sites to standard web browsers. [...] Since aws:referer value is provided by the caller in an HTTP header, unauthorized parties can use modified or custom browsers to provide any aws:referer value that they choose. As a result, aws:referer should not be used to prevent unauthorized parties from making direct AWS requests. It is offered only to allow customers to protect their digital content, stored in Amazon S3, from being referenced on unauthorized third-party sites.

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html

If you are okay with this primitive mechanism, use it, but be aware that all it does is trust what the claim made by the browser.

And that's your problem with copyObject() -- the request is not being made by a browser so there is no Referer header to validate.

You can use the StringLikeIfExists condition test to Deny only wrong referers (ignoring the absence of a referer, as would occur with an object copy) or -- better -- just grant s3:GetObject with StringLike your referer, understanding that the public warning is correct -- this allows unauthenticated access, which is what referer checking amounts to. Your content is still publicly accessible but not from a standard, unmodified web browser if hotlinked from another site.

For better security, you will want to render your HTML with pre-signed URLs (with short expiration times) for your S3 assets, or otherwise do full and proper authorization using Amazon Cognito.

Objects in Amazon S3 are private by default . There is no access unless it is granted somehow (eg on an IAM User, IAM Group or an S3 bucket policy).

The above policies are all Deny policies, which can override an Allow policy. Therefore, they aren't the reason why something is accessible.

You should start by discovering what is granting access, and then remove that access . Once the objects are private again, you should create a Bucket Policy with Allow statements that define in what situations access is permitted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM