Amazon S3 Direct File Upload from Client Browser - Private Key Disclosure

Amazon S3 direct file upload from client browser - private key disclosure

I think what you want is Browser-Based Uploads Using POST.

Basically, you do need server-side code, but all it does is generate signed policies. Once the client-side code has the signed policy, it can upload using POST directly to S3 without the data going through your server.

Here's the official doc links:

Diagram: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingHTTPPOST.html

Example code: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTExamples.html

The signed policy would go in your html in a form like this:

<html>
<head>
...
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
...
</head>
<body>
...
<form action="http://johnsmith.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
Key to upload: <input type="input" name="key" value="user/eric/" /><br />
<input type="hidden" name="acl" value="public-read" />
<input type="hidden" name="success_action_redirect" value="http://johnsmith.s3.amazonaws.com/successful_upload.html" />
Content-Type: <input type="input" name="Content-Type" value="image/jpeg" /><br />
<input type="hidden" name="x-amz-meta-uuid" value="14365123651274" />
Tags for File: <input type="input" name="x-amz-meta-tag" value="" /><br />
<input type="hidden" name="AWSAccessKeyId" value="AKIAIOSFODNN7EXAMPLE" />
<input type="hidden" name="Policy" value="POLICY" />
<input type="hidden" name="Signature" value="SIGNATURE" />
File: <input type="file" name="file" /> <br />
<!-- The elements after this will be ignored -->
<input type="submit" name="submit" value="Upload to Amazon S3" />
</form>
...
</html>

Notice the FORM action is sending the file directly to S3 - not via your server.

Every time one of your users wants to upload a file, you would create the POLICY and SIGNATURE on your server. You return the page to the user's browser. The user can then upload a file directly to S3 without going through your server.

When you sign the policy, you typically make the policy expire after a few minutes. This forces your users to talk to your server before uploading. This lets you monitor and limit uploads if you desire.

The only data going to or from your server is the signed URLs. Your secret keys stay secret on the server.

Is it safe in terms of security when uploading files to amazon s3 via http not the https?

Its not safe, and its not a good practice. What's more you should enforce any uploads to S3 to be https, which is good practice as explained in Enforce encryption of data in transit:

You can use HTTPS (TLS) to help prevent potential attackers from eavesdropping on or manipulating network traffic using person-in-the-middle or similar attacks. You should allow only encrypted connections over HTTPS (TLS) using the aws:SecureTransport condition on Amazon S3 bucket policies.

In your web app, when uploading files to S3, is it safe to upload them directly to S3 from the client side?

You should definitely do the upload via your own server, which allows you to control who gets to upload what. Many web applications have modules which simplify that.
Never take user input (and even less so uploads) for what they seem to be... You need to be able to do sanity checks, and for any sort of binary probably malware checks too.

AWS upload file from client to S3

There's no way to prevent your credentials from being seen by an user if he or she knows how to find it. The best way to handle security if you're implementing a client to S3 direct upload is to use AWS's IAM system.

Instead of giving out the key and secret of your root account or any account you would use to do administrative tasks within the AWS console, register a new account using IAM and only allow this IAM account to do PUT operations to the specific bucket (or even a specific file directory within a specific bucket). This could look something like:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1421341195000",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutObjectAcl",
"s3:PutObjectVersionAcl"
],
"Resource": [
"arn:aws:s3:::my-bucket",
"arn:aws:s3:::my-bucket/*"
]
}
]
}

Now you have an account that can only upload to your bucket. It cannot not list the items within it, it cannot update items within it, and it cannot delete items within it. On top of that, the credentials for this account cannot be used to manipulate any other AWS resources.



Related Topics



Leave a reply



Submit