Amazon Web Services signature version 1 is insecure(daemonology.net)
daemonology.net
Amazon Web Services signature version 1 is insecure
http://www.daemonology.net/blog/2008-12-18-AWS-signature-version-1-is-insecure.html
48 comments
This is a lovely reminder that designing cryptographic protocols is hard. Even something as simple as signing a bit of data can have nasty pitfalls.
I wouldn't say that this shows that designing cryptographic protocols is hard. "Use hashing and signature methods which don't have collisions" is a simple rule, both to remember and to apply -- no harder than "drive on the right side of the road" (or "drive on the left side of the road", depending on your country).
Would you say that driving is hard because people have to remember which side of the road to drive on?
Would you say that driving is hard because people have to remember which side of the road to drive on?
If there were 40 sides of the road to choose from, and the side you drove on depended on the time of day and the color of your car, then yes, Colin, I would say driving on the correct side of the road would be hard too.
Have you ever, in your whole career, worked with a team that wrote their own crypto and got it right in version 1? Because I haven't.
Have you ever, in your whole career, worked with a team that wrote their own crypto and got it right in version 1? Because I haven't.
Have you ever, in your whole career, worked with a team that wrote their own crypto and got it right in version 1? Because I haven't.
As far as I know, I got the crypto right in tarsnap. If I didn't, please let me know. :-)
As far as I know, I got the crypto right in tarsnap. If I didn't, please let me know. :-)
I don't think you really answered my question, Colin; I think that's a cop-out answer. =)
Maybe I misunderstood your question. I thought that "as far as I know, I got the crypto right in [product where I wrote my own crypto protocols]" was a pretty clear answer to "have you ever written your own crypto and gotten it right?"
I was asking if you'd ever worked with a team of (other, I implied unsuccessfully) developers who got a cryptosystem right on the first try.
Ok, that explains it. I didn't catch the fact that you were excluding the degenerate case of a one-person team. :-)
I also assumed you'd like your own stuff. But, now that we understand each other: was that an answer to my original question?
I believe I got the crypto right in version 1 of tarsnap, but I wasn't working as part of a (non-degenerate) team. I've never done crypto with a team -- so my answer to your (clarified) question must be a vacuous "no".
But you've worked against a couple teams now that got it wrong (Amazon, OpenSSL). Do you agree that the evidence supports my argument?
Not really, no. Amazon screwed up on a well-known widely-understood rule; there aren't 40 different sides of the road involved with "hash collisions are bad".
Similarly, the one cryptographic complaint I have about OpenSSL (as opposed to non-cryptographic security bugs) is their lack of attention to side channels, and the same applies here -- we KNOW that side channels are bad. The fact that the OpenSSL developers haven't made any systematic attempt to prevent them doesn't mean that cryptography is hard; it just means that the OpenSSL developers are careless.
Similarly, the one cryptographic complaint I have about OpenSSL (as opposed to non-cryptographic security bugs) is their lack of attention to side channels, and the same applies here -- we KNOW that side channels are bad. The fact that the OpenSSL developers haven't made any systematic attempt to prevent them doesn't mean that cryptography is hard; it just means that the OpenSSL developers are careless.
My assumption is that the Amazon people felt that by using HMAC-SHA1 they were secure because that's a well known way of hashing and signing something. The pitfall was in their implementation. They have such a simple system, yet they managed to make a mistake.
This sort of problem is one of the reasons that I made the crypto in tumbler (http://tumbler.sf.net/) as simple as possible because I was sure that if I did anything but total simplicity I would screw it up.
This sort of problem is one of the reasons that I made the crypto in tumbler (http://tumbler.sf.net/) as simple as possible because I was sure that if I did anything but total simplicity I would screw it up.
And because Tumbler is basically a dumbed-down version of the RADIUS protocol, you still wound up with the same major security flaw: if you sniff a Tumbler message off the wire, you can crack it with an incremental SHA256 cracker (which is much faster than Unix crypt).
You told people to pick good "passwords"; you should change the language to say "generate good 128 bit random strings".
You told people to pick good "passwords"; you should change the language to say "generate good 128 bit random strings".
Does it worry anyone else that there seems to be no protection provided against replaying any particular authenticated request? If I were using this service, I'd heavily recommend restricting non-https requests to read-only operations. Any updates or deletes should be done using a security protocol proofed against replay attacks, like HTTPS.
At least in the case of SimpleDB, replaying requests is usually not a problem -- if you Put or Delete an attribute which has already been Put or Deleted, it has no effect.
Sorry, but you aren't thinking like a security professional here. Consider the case, e.g., where you create a domain, delete it and recreate it. An attacker monitoring the deletion can with impunity wipe out your data at a later date.
I did say "usually". :-)
An attacker monitoring the deletion can with impunity wipe out your data at a later date.
Only within the next 15 minutes. Beyond that point, AWS will reject the request for having excess clock skew.
An attacker monitoring the deletion can with impunity wipe out your data at a later date.
Only within the next 15 minutes. Beyond that point, AWS will reject the request for having excess clock skew.
Ew! They use the timestamp parameter for that? That's both sick and wrong. Requiring people who access your webservice to have an accurate clock is the most braindead thing I've heard this month, at least. Oh boy, network congestion and clock skew could combine to produce some wonderful heisenbugs for developers. And for what? The want of nonce? Some ridiculous design principle of making your API totally state free. sigh
State-free protocols are useful when the server side is distributed and potentially disconnected. :-)
As for "wonderful heisenbugs" -- the AWS services return a clear "hey, your clock is broken" error, so it wouldn't be very hard to developers to figure out what was going on.
As for "wonderful heisenbugs" -- the AWS services return a clear "hey, your clock is broken" error, so it wouldn't be very hard to developers to figure out what was going on.
Plenty of well-regarded crypto protocols use timestamps to prevent replay. The nonce isn't a panacea; you have any number of design pitfalls to deal with when trying to secure a message with a random number, too.
This is interesting: I submitted this article both here and to programming.reddit.com; but at the same time as becoming the top story on news.yc, it got voted down on reddit (well, 1 up vote, 2 down votes).
I wonder if this is just the random luck of who happened to see the post on reddit first, or if news.ycers are innately more interested in security-related stories than programming.redditers.
I wonder if this is just the random luck of who happened to see the post on reddit first, or if news.ycers are innately more interested in security-related stories than programming.redditers.
You may have a better brand name on news.yc.
Example #489643876834 of why you, a very smart, very capable developer, should not be writing crypto code. Rule #1: if you have to type the letters A-E-S or S-H-A into your code, you're doing it wrong.
There are pretty big mistakes to be made on the other side of this philosophy as well. If you need to solve some cryptographic problem which is not exactly the same as something which has already been designed, implemented, and reviewed by competent cryptographers, then you essentially need to create a new protocol and accept all the pitfalls which that entails.
PGP seems to be a popular 'primitive' to try to roll your own broken crypto protocol out of.
Exhibit A: http://enigform.mozdev.org/
Exhibit B: http://web.monkeysphere.info/
Even SSL/TLS is not easy to use correctly (while understanding all the risks) for purposes other than what it was originally designed for: Preventing credit card numbers from being sniffed between a browser and a web merchant.
PGP seems to be a popular 'primitive' to try to roll your own broken crypto protocol out of.
Exhibit A: http://enigform.mozdev.org/
Exhibit B: http://web.monkeysphere.info/
Even SSL/TLS is not easy to use correctly (while understanding all the risks) for purposes other than what it was originally designed for: Preventing credit card numbers from being sniffed between a browser and a web merchant.
Design a transport security protocol that is different in some way from TLS, and a good chunk of those differences are going to be vulnerabilities that the TLS designers figured out that you missed.
SSLv1 may have been originally designed for securing credit cards, but I'm not sure that argument survives a close read of TLS; why waste time with mutual authentication, with forward secrecy, with a custom record layer, with arbitrary length certificate signing chains, etc etc etc. You might be surprised at the number of systems that leverage TLS successfully on ports other than 443.
We probably agree; no matter how you choose to implement crypto security in a system, you're probably worse off for trying.
SSLv1 may have been originally designed for securing credit cards, but I'm not sure that argument survives a close read of TLS; why waste time with mutual authentication, with forward secrecy, with a custom record layer, with arbitrary length certificate signing chains, etc etc etc. You might be surprised at the number of systems that leverage TLS successfully on ports other than 443.
We probably agree; no matter how you choose to implement crypto security in a system, you're probably worse off for trying.
Forward secrecy was one of the important mistakes I had in mind actually. If you use TLS naively, you have none. You probably didn't even realize you needed it.
Verifying certificates correctly is not so easy to get right either, if you can even figure out what PKI means for your particular application in the first place.
Verifying certificates correctly is not so easy to get right either, if you can even figure out what PKI means for your particular application in the first place.
Certificates are a lot like git branching. They're intimidating if you consider them in their entirety, but simple if you stick to your old use cases.
Enterprise apps make good use of certificates. A common use case is to set up a private CA (a three-line shell script) and issue internal certs to all endpoints in a system; you can then do crypto-strong access control just by checking signatures. This is approximately to PKI what "using git just like you used Subversion" is to git.
Another place where TLS has been a huge win is in wireless security; EAP-TLS with mutual certificate auth is the de facto corporate wireless security standard now.
Enterprise apps make good use of certificates. A common use case is to set up a private CA (a three-line shell script) and issue internal certs to all endpoints in a system; you can then do crypto-strong access control just by checking signatures. This is approximately to PKI what "using git just like you used Subversion" is to git.
Another place where TLS has been a huge win is in wireless security; EAP-TLS with mutual certificate auth is the de facto corporate wireless security standard now.
You seem to be knowledgable on these topics, so I have a question... If I take the query string parameters and then a ridiculously long pre-determined salt (30 chars) to create a SHA-256 signature for POSTing, what's the chance that this will actually result in collisions / cracking?
Even if null data is submitted and someone sniffs the salt, it's still 30-chars long and last I checked rainbow tables don't work too well on SHA-256 hashes of that length.
I ask because I use a system similar to this to just do a basic check to ensure that a form POST is coming from a user clicking an action and not just some random spammers' form just posting the needed vars. It's nothing particularly secure (I think), just a nuisance to any spammer.
Even if null data is submitted and someone sniffs the salt, it's still 30-chars long and last I checked rainbow tables don't work too well on SHA-256 hashes of that length.
I ask because I use a system similar to this to just do a basic check to ensure that a form POST is coming from a user clicking an action and not just some random spammers' form just posting the needed vars. It's nothing particularly secure (I think), just a nuisance to any spammer.
First, you're talking about a nonce, not a salt. You'd be a happier person if you took the word "salt" out of your CS vocabulary.
Second, the vulnerability here isn't password cracking; it's that AMZN verifies the signature on canonicalized data, but operates on non-canonicalized data.
Second, the vulnerability here isn't password cracking; it's that AMZN verifies the signature on canonicalized data, but operates on non-canonicalized data.
Thanks! I understand the Amazon vulnerability fully, I was just referring to my own web-app development.
It's not an issue though because I don't do the key/value pair splitting as they do.
It's not an issue though because I don't do the key/value pair splitting as they do.
Why are you "signing" your data at all? You're doing it wrong. Use SSL to secure the whole transport; use form or HTTP auth to make sure you know who you're talking to.
[deleted]
Signing requests with an HMAC provides end-to-end authentication, which is vastly superior to transport-level authentication such as HTTP auth.
You skipped the HTTPS part of my recommendation, which is vastly superior to homebrewed HMAC.
HTTPS is irrelevant to what I said. End-to-end authentication is better than transport-level authentication. Using an HMAC to sign requests and then sending those signed requests over HTTPS is better than using HTTP auth over HTTPS.
Yes, but what you said is irrelevant to what I said, and so we are at an impasse. =)
The developer who made this mistake probably didn't think s/he was writing crypto code. (Switching to "he" for brevity) He probably thought he was merely making use of someone else's crypto code. The mistake was in choosing what string to sign, not in the function applied to that string after it was chosen. I think the real lesson here is that if your app needs cryptography, then you need at least a black-box understanding of what crypto does and doesn't do.
In my experience, the people who do the worst at building secure systems are the ones who know "just enough" about how crypto works. These are the people who implement Diffie-Hellman and don't check parameters, the people who implement AES in ECB mode, the people who store passwords hashed with ultra-fast digest schemes, the ones that leak timing information or cipher state in distinguishable error messages, and the people who implement mirrorable challenge-response protocols.
The "dumb" developers just use OpenSSL and PGP, and they usually come out ahead in the end.
Also: I doubt the Amazon implementers here were dumb. I bet they were pretty smart. They just forgot about canonicalization; this is a classic problem in signature systems. Building crypto features is a good way to get screwed.
(PS: I feel qualified to take a contract breaking systems like this, but probably not qualified enough to engineer my own crypto protocol.)
The "dumb" developers just use OpenSSL and PGP, and they usually come out ahead in the end.
Also: I doubt the Amazon implementers here were dumb. I bet they were pretty smart. They just forgot about canonicalization; this is a classic problem in signature systems. Building crypto features is a good way to get screwed.
(PS: I feel qualified to take a contract breaking systems like this, but probably not qualified enough to engineer my own crypto protocol.)
i believe flickr's api uses the same method of creating signatures.
I just looked at the flickr API documentation, and it looks like you're right -- maybe that's where Amazon got the idea from. I'm not sure if it's a problem in flickr's case, but I'll send them an email pointing out the possible problem.
Since the delimiters are removed before computing the signature (so each is just "ABCDEFGHIJLM"), the signatures for the following two query strings are the same:
So if the value of of the E parameter is controlled by the user, they can construct a value ("HIJKLM") such that the resulting signatures is the same as the signature for a query with a bunch of additional parameters they choose ("H=I&J=K&L=M").
Clever.