-1

I can able to generate preSignedUrl and add Expration (For uploading an Image) successfully but how can I secure the url from a malicious person.

like for example in my nodejs server i have users who can post images, and some hacker logs in to my website get his jwt token, gets his s3 preSignedUrl and abuse my s3 storage.

how do I increase security ?

You can visit my website to get a presignedUrl to post a file visit : http://khelkhelo.in

// This is how I reproduce how a hacker can abuse the service

const { default: axios } = require("axios");

async function uploadFromMaliciousSource() {
  // hacker will create account in my website and get his own jwt token

  // signedurl we are using here is to upload images in a user post

  const { data: signedUrl } = await axios.get("http://khelkhelo.in", {
    headers: {
      "x-auth-token": "jwt token of a user",
    },
  });

  // here hacker can have access to preSignedurl and can upload his OWN CONTENT like sharing movies

    const formdata = new FormData()
    formdata.append() // ... 
}

uploadFromMaliciousSource();


Juno
  • 41
  • 7
  • *"some hacker logs in to my website get his jwt token, gets his s3 preSignedUrl and abuse my s3 storage"* - at that point you have lost already. If you lost the jwts you f*'%ed up and are done for, not much you can do, that simply must not happen. Presigned urls are secure based on the fact that they simply cannot be guessed. Whoever has the url can access the data. – luk2302 Sep 07 '21 at 12:10
  • ah, I missed to add preSigned Url for uploading files, a hacker can make use of my website api to get presignedurl to upload a image but here in this case he can able to abuse the service – Juno Sep 07 '21 at 12:17
  • *"jwt token of a user"* - as noted already if someone discovers a JWT from some user you basically cannot do anything. It is basically like they telling someone their password, that is no longer your problem but of the person who lost their jwt, unless your code is actually the one leaking the info. – luk2302 Sep 07 '21 at 13:20
  • jwt code is perfect, im talking if the hacker is a user of my website and he has his own jwt token, – Juno Sep 07 '21 at 13:31
  • So what is the problem then? You want to prevent a user from uploading a lot of images? Then implement some logic to rate limit that endpoint to request a presigned url only every e.g. 10 minutes? – luk2302 Sep 07 '21 at 13:32

2 Answers2

2

An Amazon S3 pre-signed URL should be generated by your back-end server. It grants temporary permission to upload or download an Amazon S3 object.

The pre-signed URL is 'signed' with your AWS Secret Key. This is why the back-end must generate the URL, rather than the front-end. It is not related to a JWT token.

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
1

To prevent hackers getting these S3 pre-signed URLs, you should require authentication to your service. Your question then seems to be: how do I prevent hackers authenticating to my service?

The answer depends on how serious the consequences of such a hack are and what level of inconvenience you want your legitimate users to experience.

Potential solutions include a combination of approaches. This is not an exhaustive list but just to give you some ideas:

  • end-to-end TLS encryption and secure handling of certificates
  • complex, lengthy passwords or IDP-based authentication
  • disabling account for some period of time after N bad login attempts
  • multi-factor authentication
  • geo or IP-based restrictions
  • use of have I been owned services
  • behavioral analysis of user interaction with your site
  • rate-limiting client requests
  • web application firewall
  • short duration API keys, with invalidation capability
  • revoke list of JWT tokens

Note: once you've given a pre-signed S3 upload URL to an end user (whether that's the intended user or not), that URL remains valid and usable until it expires. If reused before expiration, it will cause any existing object at that same key to be overwritten (so there's limited scope for abuse of your S3 bucket). You could also implement a Lambda-based solution that triggers your ingestion workflow on the first upload to a given S3 key but not on any subsequent upload to that same key.

jarmod
  • 71,565
  • 16
  • 115
  • 122