S3 bucket policy via a particular application - security

I am trying to utilize S3 to let my clients download my software package. What I envision is creating a simple web app with authorization For example (download.mysoftware.com) Once the user is authenticated, they will be presented with a S3 url used to download the software. I will create user accounts based on my customers.
My concern is, what happens if the user copies the S3 URL link and then gives it to someone who isn't authenticated to download the software?
Is it possible to create an S3 policy that would prevent this and work for my usecase? I looked at allowing only specific IPs, however, I won't have a way to find out IP of my customers and wouldn't want to ask them first and then add it to the policy each time.
One way allowing specific IPs would work is if I allow downloads only from the IP that is linked to (download.mysoftware.com) but then the downloads will really be happened from my web application as opposed to from S3. Which seems like double effort.

When a user makes a request to download your application, generate a pre-signed URL for them with a short expiration. It only needs to be valid for as long as it takes them to start downloading your file, so even a few minutes of validity is likely to be plenty.
While it's technically possible for a user to share one of these URLs, they would have to convey the URL to someone else and get them to download it very quickly, which is probably sufficient to deter them from trying to share the URL. (A perfect defense is more difficult, and is probably unnecessary anyways; there's no way to prevent a user from personally transferring a file they downloaded to someone else.)

Related

How to prevent snooping by user of Mac app?

I am creating a Chromium/Electron based Mac app. The app is essentially a browser for my customers to use a web service that I have no control over. My requirement is that users of my app (who may have root access on their Mac) should not be able to view the URLs the app is visiting, and should be unable to gain access to the cookies the app is storing. Normally it is not hard to MITM yourself, or attach a debugger to an app and dump memory to see the URLs and cookies.
How can I prevent these types of leaks to the user? If it's impossible, it may be acceptable to make it very hard so that a very high level of sophistication is needed.
Your users have full control of their devices, it is not possible to securely prevent them from proxying or exploring what your client-side app does. Obfuscation would seem like an option, but in the end, the http request that leaves your app will traverse the whole OS through different layers, and your user can easily observe that, if not else then in network packets (but usually much easier).
The only way it is possible to prevent the user from knowing what's happening is if you have your own backend. The frontend app (Electron) would make a request to your backend, which in turn could make any request with any parameters without the user being aware.
Note though that your backend could still be used as a proxy or oracle just like if the user was connecting to the real service. This might or might not be a problem in your case, depending on what you actually want to achieve and why.
The app is essentially a browser for my customers to use a web service that I have no control over. My requirement is that users of my app (who may have root access on their Mac) should not be able to view the URLs the app is visiting, and should be unable to gain access to the cookies the app is storing
Basically, you cannot (you could with the appropriate infrastructure. But you lack that infrastructure).
Network communications can be secured, to a point, using HTTPS (if you can't even use that, then you're completely out of luck - users wouldn't even need root access to the Mac to sniff traffic). You need to verify the server certificate to be sure you're connecting to the correct server.
One thing you might do - effectual just against wannabes, I'm afraid - is first run a test API call on some random server and verify that the connection either fully succeeds, with the proper server identification and matching IP, if the server exists, or that it properly fails if the server never existed. Anything else would be a telltale that someone has taken over the network layer, and at that point you could connect to a different server, making different calls, and lament that the server isn't answering properly.
Strings in memory can be (air quote) protected (end air quote) by having them available only for the shortest time, and otherwise stored in a different form - you can have for example an URL and a random byte sequence with the same length, then store the sequence and the XOR of the URL and the sequence. You can then reconstruct the URL every time you need it, remembering to clear it off any app caches it might find its way into. Also, just for the lols, you can keep a baker's dozen of different URLs sprinkled in the clear throughout the code. A memory dump at that point will turn out nothing useful.
Files, of course, can be encrypted with any one of several schemes - the files residing on the same machine that has to know how to decode them makes all such schemes ultimately vulnerable, but there again, you can try and obfuscate things. I once stored some information in a ZIP file - but it was just the header of an encrypted ZIP file, with the appropriate directory entry block glued at the end. The data were actually just gzipped in the clear, there was no password whatsoever. The guys that tried to decode the file thought it was a plain encrypted Zip file with the extension changed, wasted a significant amount of time with several Zip cracking tools, and ended up owing me a beer.
More than that, there is not much that can realistically be done.
A big advantage would be in outsourcing the API calls and "cookie" maintenance to an external service that you control, e.g. on Amazon AWS or Azure or similar. Then you could employ all kinds of protection schemes (for example: all outbound API calls could be stored in an opaque object, timestamped, nonced, and encrypted with your server's public key, and the responses sent encrypted with your client's unique key). Since this is relatively simple and cost-effective, it would also be my recommendation.

Risk of malware when uploading/downloading user files

I'm building a social app, where users can choose what profile-picture they wish to display to others. I've currently implemented it as the following:
User sends the profile-picture file to my server
My server validates that the file size is not too large
My server uploads the file to a AWS S3 bucket, with a UUID prefix
The S3 bucket allows anyone in the world to download specific files, but not perform write/list operations
I store the profile-picture URL in my database, and send the link to other users as appropriate
The client for other users, upon encountering the profile-picture URL, will download the file and display it to the user
I'm now wondering if it's possible for a malicious user to upload a malware-file as his profile-picture, and take advantage of the fact that this malware will be stored in my S3 bucket, and downloaded onto many other users' phones.
How much of a concern is the above? Is there anything simple I can do to prevent such concerns? If not, what is the recommended way to store/distribute user-uploaded profile-pictures to others?
Edit: My server is in Java. Any Java specific library/tool advice will be appreciated as well

Amazon cloudfront how to set signed url outdated if used one time

I need to protect my videos to be downlouded using "Internet Download Manager - IDM/IDMan"
i used
1. rtmp stream
2. signed URL
3. expiration date of signed URL (60seconds)
4. i set player(jwplayer)to *autostar*
AND i need to set signed url outdated if it used one time
using this solution IDM will get an url that is already used then blocked
Is there any way to configure cloudfront to use signed url just one time;
Or any solution that can protect videos to be uploaded and used in other web sites.
Please can you help?
Thanks in advance
Cloudfront does not support the ability to only play a url once and they never will. The reason is that the only way to do this will be for all their edge servers to share the information - they currently do not share state which means scaling is much easier and performance is much better.
Unfortunately, if you're looking for fine grained control over how your videos are played, you're going to need more fine grained code, which you can't do in cloudfront - you'll need to host content directly on your server.
Idea 1: Limit by count
You can implement the idea that you have - once the url has been used once, you no longer serve up that file.
Idea 2: Limit by referrer
You can look at the referrer header and if it's from your website, then allow the content to be downloaded. Otherwise, reject it. Note: this can be spoofed and a user can set the referrer header manually.
Preventing a video from being downloaded and later uploaded is technically impossible. By letting them display the video, there really isn't any way to do that without them being able to record those bits and replay them later. There are probably things, like preventing right clicks or using an odd proprietary format or something else but I'm not familiar with DRM techniques.

How to secure S3 download for user sensitve data?

Suppose we have a web application for ebook shopping, users can only download books they have paid. And all those ebooks data(like epub data) are stored in S3, users will got a S3 download url when our app validated the user already bought one book.
I know S3 will generate a temporary and time-limited URLs to the user. But the problem is even the url is temporary and time-limited, what will happen if by any chance another user get the temporary url within the limited time?
Ok so one way seems to be letting the limited-time very short, like 10 seconds, but the potential risks still there.
I know this question is rigorous, how would you deal with it? Or forget it?
If the concern is that the buyer would distribute the URL, they could equally well distribute the file they've downloaded.
If the concern is that someone would get hold of the URL without the buyer's knowledge, then perhaps you could protect the download with a token that only the buyer would know (e.g. a password of some sort). This would make the URL unusable to anyone other than the buyer. The downside is that this will inconvenience the very people who've paid for your product.

What's a good approach to securing MP3 files for a private podcast with Amazon S3?

I'm trying to create a private podcast feeds. Each user of my service gets an account and depending on what they pay, they will receive different content. Some content is sensitive so security is reasonably important; if any of the enclosed audio files made the rounds around the internet, it could be catastrophic for our business.
I am currently prototyping the service and MP3s are stored on S3 and they are not secured. It's time to secure them. From my research, I understand that I can, in fact, secure files on S3 with an access expiry period. But, because I have many users, signing the request with my "global" key and have an expiry probably isn't a good idea because
If I need to revoke access, I'll need to do it for everyone
Since I don't know when, exactly, their podcatcher will request the file, I don't know when to set the expiry. Sometimes, the podcatcher downloads the feed XML, but only later fetches the MP3 file so the URLs could expire before the client has a chance to fetch them (I'm thinking about iTunes, but there could be others).
The way I see it, I have two options and I'm not sure if either are workable:
Edit Another potential way, I suppose, would be to role my own security, and simply redirect to an MP3 on S3 with a short expiry if the user is good to go. This seems most sensible.
I can create user accounts on Amazon for ALL of my users and link them to an Amazon token in my database. Everyone's MP3 urls are signed with their secret token and expiry a long time from now. I don't like the idea of storing their tokens on my database, and I'm not sure if the Amazon ACL was designed for this scenario. It also means the files can still be shared if you know the URL.
I can proxy every request through my server. This means I only have one Amazon account, and I can role my own security system. But proxying every MP3 download through my server sounds slow, wasteful and expensive.
Any ideas on the best way to do this.
P.S. I'm not married to S3. Other solutions could be considered. And I'm on Heroku using Ruby, in case you care.
I am going with the redirect solution suggested elsewhere. This seems to give me the most flexibility and very low overhead. What you definitely should not do is is using links directly to S3 in your feed, because they likely expire before they are downloaded by the client.

Resources