The AWS S3 Denial of Wallet Amplification Attack
blog.limbus-medtec.com
blog.limbus-medtec.com
AWS user believes that testing on a 1Gbps connection for 45 min can't be more than $10 of egress.
Gets a $500 bill instead.
Note: This user specified a lower range but not an upper range on the request (and closed the connection prematurely). Essentially read() with an offset, for a ZIP tool.
> Amazon S3 attempts to stop the streaming of data, but it does not happen instantaneously.
...which doesn't really explain it. It shouldn't send more than a TCP window after the connection is closed, and TCP windows are at most 1 GiB [1], usually much less, so this completely fails to explain the article's observed 3 TB sent vs 130 TB billed.
The article goes on to say:
> Okay, this is half the explanation. AWS customers are not billed for the data actually transferred to the Internet but instead for some amount of data that is cached internally.
In other words, how much they bill really isn't bounded by how much is sent at all. This is unacceptable.
I interpreted that to be that their code was doing this over and over again, so in total they retrieved 3TB over a set of requests. Still horrifying, but mildly more explainable.
One could disprove this explanation with a packet capture; just add the remaining window.
S3 is a block storage, so retrieving an object for such a high availability and high perf service means it tries to pull some X block of data and cache it before sending through the socket.
That X block of data is out of internal S3 storage, just not sent through the bigger Internet egress subsystem.
So technically aws may argue this is egress for s3, just not for aws
if you think egress is expensive, well storing data in RAM for cache purposes is 1000000x more expensive
a lot of stuff could be happening. Main problem is AWS (i think) is charging for egress out of S3 system, but customers are looking at their ingress at client side and there is mismatch
Charge for the buffer you fill: sure.
Charge the theoretical maximum: silly.
But egress fees only apply to S3 transfers outside AWS?
So which is it? Data transferred to the Internet? Or data processed internally?
Right now some class action lawyer is drooling.
Like, charging for requests or internal data processing, sure okay.
But this is a charge specifically for the data transferred from AWS to the internet. So if you're not transferring data to the internet....
I mean, we already know egress is short for egregious. It’s an incredibly bad look to be overestimating the “fuck you” part of the bill.
- A client sends range requests and cancels them quickly.
- The full range request data will be billed (NOT the whole file), so I think this should read that the entire requested range gets billed, even if it never gets transferred (the explanation we received for this is that it's due to some internal buffering S3 is doing, and they do count this as egress).
In any case, if you send and cancel such requests quickly (which is easy enough, this was not even an adversarial situation, just a bug in some client API code) the egress cost is many times higher than your theoretical bandwidth (and about 80x higher than in the AWS documentation, hence the blogpost).
From the OP it sounds like the amount billed is too high to be explained by that.
If what you are billed for isn't actually data transferred, then it is deceptive to say that you are billed for "data transferred out".
It also seemed like the root cause was an interrupted range request (although I wasn't fully clear on that). Even so that seems like a recent regression. It took me ages to get that stupid app working, I interrupted a lot of range requests :)
Not if it's cross-region.
Is there a billed difference between Range: 0-, no "Range" header, and Range: 0-1GB if the client downloads 400MB in each scenario?
On top of this, S3 already bills (separately) for any request against a bucket (see the other current issue with the invalid PUT requests against a secured bucket, which still got billed to the bucket owner; https://news.ycombinator.com/item?id=40203126). So I'd say both the requests and the cancellations were already paid for; the surprise was the 'egress' cost on top, of data that was not actually leaving the AWS network.
Still, you are right that this still consumes some additional AWS resources, and it is probably a non-trivial issue to fix in the 'billing system'.
https://learn.microsoft.com/en-us/azure/cost-management-bill...
The simple truth is it's good for their earnings report if they have unrestricted access to your wallet
It leads to a "bad customer experience", having to update lots of code, and also increases maintenance costs while you keep two separate code paths functional.
There's a lot about the S3 API that would be changed, including the response codes etc., if S3 engineers had freedom to change it! I remember many conversations on the topic when I worked alongside them in AWS.
https://news.ycombinator.com/item?id=40203126#40205213 https://github.com/ZJONSSON/node-unzipper/issues/308
Maybe that's just our non-native English shining through. In any case, as a small European company in the healthcare space, we are quite used to having to explain "the cloud" (with all potential and pitfalls) to our customers. They are also (part of) the target audience for this post, hence the additional explanations.
(Not OP and not author of the article, but was involved in the write-up.)
- Stop using S3 and other AWS (perhaps it stands for Amazon Web Scams?) things already and switch to Cloudflare R2...
I hope this doesn't result in any significant changes as I really liked using this pattern for sequential data processing of potentially large blobs.
At least 500-600 words weren't needed and just added noise to the article, making it harder to read.
AFAIK cannot be protected against
https://twitter.com/Lauramaywendel/status/178506487864384308...
R2 also doesn't have all the features that S3 does - including an equivalent of S3 Glacier, which is cheaper storage than R2. R2 also doesn't have object tagging, object-level permissions, or object locking. Sure, you could build your own layer in front of R2 that gives you these features, but are you necessarily saving money over just using S3?
As others mentioned, it still lack many features if compared to S3.
CloudFront charges for all requests, so a 404 Not Found, will be counted towards the total number of requests, and you will be billed accordingly. Hopefully somebody will prove me wrong :-)
So your S3 bucket names must be hidden passphrases now that stand between an attacker and your budget.
The new thing is hyperscalers have so much capacity you can get flooded by these long before the service degrades or goes offline
Cloud computing charges you by the request/byte/cpu cycle. Servers do not have this issue.
Also, is it simply not possible to rate limit this on a per IP basis? Make client only able to do X requests per second from each unique IP/network flow.
Sure they do. Processing requests takes bandwidth, CPU, memory, disk I/O
>Also, is it simply not possible to rate limit this on a per IP basis
It's largely useless. You'll block any legitimate bits/programs, people on CGNAT, people on corporate networks & bad actors will use botnets, residential IPs, VPNs to gain access to thousands or millions of unique IPs
Thankfully, it does look like AWS is appropriately embarrassed over this, and is going to maybe do something.
e.x. build an installer and distribute it, generate a report and generate a signed url