1

I am currently developing against a RESTful API that seemingly has a rather weird auth flow. I got an API key consisting of an ID (public) and a "secret" (which seems to be a UUID).

Now, whenever I want to call the API, I have to do the following:

  1. Create JSON request body
  2. md5-Hash of (API-URL, Request, ID, Secret)
  3. Set ID as header field "UserId" of request.
  4. Set generated hash as "Authorization" header in the API call.

I assume that the receiver pretty much does the same hashing (and knows the secret of my ID) and compares the results.

However I think this is really wonky as

  • The JSON request body becomes case sensitive due to the hashing. If I add one space, the hash is different and auth fails.
  • They "roll their own" security related things it seems.

These issues are rather broad though. I would like to know what flaws are in this implementation that I am currently not seing?

1

The concept of calculating some form of hash over (url + request payload + ...) is not something uncommon. I wouldn't say it is flat out wrong.

There are a few problems with this specific implementation, though:

  • MD5 is not considered secure. SHA-2 would be a much better choice.
  • There doesn't seem to be any protection against replay attack. Adding e.g. unix timestamp in the header and including it in the input to hash calculation could help. Server-side timestamp validation necessary.
  • Including nonce in the payload could help. No two otherwise same requests would result in the same hash.
  • I find calculating a hash over an input including secret a bit unusual. Why would you like to do that? More common solution would be to calculate HMAC, e.g. HMAC-SHA256 instead, and exclude the secret from HMAC calculations. HMACs provide you with authenticity, as only the party with access to the key can generate correct authentication tag. I believe authentication was the reason why the secret was originally included. With key-based HMACs, the use of uuid-like secret could be abandoned.

I wouldn't be worried about the payload being case-sensitive, extra whitespaces etc. If you implement it right, it will work. And then obviously the server has to calculate the hash (or better HMAC) and compare it with the one it received, in case of differences I expect it would respond with 401.

2
  • This is actually one of the few use cases in which MD5 is still considered "secure enough". While MD5 does have some cryptographic weaknesses, it is mainly vulnerable to collision attacks, while this would be a preimage attack. From that perspective it has the advantage of being fast. Jul 12 '20 at 18:57
  • 1
    (although to be clear, an HMAC is much better, and this is all pointless without a signature to prevent replays) Jul 13 '20 at 1:35
0

Everything about this is unnecessary and redundant. Ignoring the problems with MD5, it adds nothing of value over a simple opaque bearer token and TLS.

I would like to know what flaws are in this implementation that I am currently not seing?

Again, use of MD5 not withstanding, the specific flaws in "signing" the entire request is simply that it adds complexity and brittleness for no value, assuming real security is provided by TLS and proper client authentication.

There are probably other short comings in their implementation:: Can your secret be revoked? Rotated without downtime? None of that really matters next to the fundamental flaw hat this entire system is simply unnecessary in the first place.

Regarding your specific concerns...

The JSON request body becomes case sensitive due to the hashing. If I add one space, the hash is different and auth fails.

JSON is already case-sensitive, and if your request body doesn't arrive byte-for-byte exactly as you sent it, this is a huge problem. But you shouldn't have to worry about this, or enforce it with some sort of hashing/signing done at the application level. The transport level takes care of this for you.

2
  • Implementing request signing is actually quite common. See for instance the hoops you have to jump through to make a call to AWS: docs.aws.amazon.com/general/latest/gr/sigv4_signing.html Jul 12 '20 at 19:03
  • Which, for further details, one important reason is to prevent replay attacks. While it is true that TLS prevents replay attacks at the network layer, you need additional protections at the application layer. Without signing the request (specifically including the timestamp) an attacker who managed to get a copy of the request payload could resend it to the server and repeat the action. The other advantage is that you don't have to send up your secret key - you just use it to generate the signature Jul 13 '20 at 1:34
-1

Deprecated Hash Algorithm

The MD5 hash algorithm has been deprecated by SHA1, and the latter same thing by SHA-2, so it may be a better idea to use something like SHA256. NIST won't bother mentioning MD5 as an alternative.

It is some 12 years since MD5 was broken by a team of researchers, nobody should be using it as of now.

The expert's recommendation is to use something more current like SHA256, which won't take a toll with today's processing capabilities. Even those new options will fall down sooner rather than later.

1
  • There is an important difference between collision attacks and preimage attacks. When it comes to collision attacks (aka your article), MD5 is quite broken. However it can still withstand preimage attacks, which is relevant here. So while usage of MD5 is still perhaps not the best choice, it is actual secure in this context. Jul 12 '20 at 18:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.