3

We have SSL communication between our mobile app and our servers.

The request from mobile is creating a hash on all the request fields - based on a secret key which is "stored" on the app.

So it sends json with all the fields data, plus a signature value which is :

hash = hashBasedOnKey ( all request data fields)

Later, the server does the same thing. It reads the fields and run hash on those fields ( server also has the secret key) and if the hash are the same , then it means that the data was not altered.

But

Is it really needed when using SSL communication ?

A MITM can't alter the data , except for SSL stripping. But again, the mobile app uses SSL communication.
IMHO - ssl stripping is when non ssl "thinks" it connects to ssl , without noticing, where the MITM does the SSL by itself to the destination, and strip the https data , and return the http data.

Question:

Is hashing the data in the client, crucial? or is it useless?

Z.T.
  • 7,768
  • 1
  • 20
  • 35
Royi Namir
  • 351
  • 3
  • 12
  • It depends, as ever, on your [threat model](https://en.wikipedia.org/wiki/Threat_model). Who are you trying to defend against? What attacks are you trying to prevent with this? Sounds like you're trying to prevent tampering -- in that case, you're probably better off using [authenticated encryption](https://en.wikipedia.org/wiki/Authenticated_encryption) on the entire message, rather than just picking and choosing certain fields. Otherwise, you might be vulnerable to a variant of [parameter pollution](https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004)). – Nic Jul 10 '19 at 20:29
  • @NicHartley we are generating hash on the entire message. question is , should we ? ( on ssl) – Royi Namir Jul 10 '19 at 20:39
  • I edited your title for understandability. I hope you actually use HMAC and not just keyed hash, or else you're vulnerable to length extension attacks. – Z.T. Jul 10 '19 at 21:03
  • 1
    @Z.T. Yes we use hmac("_hash on all the request fields - based on a secret key_") . Question , is it needed in tls for tempering check.... – Royi Namir Jul 10 '19 at 21:05
  • 1
    Naively, HMAC of arguments passed over TLS is useless. Unless you can articulate the exact threat this mitigates - it's useless. Maybe it is an anachronism, used to be needed but no longer. Maybe it was cargo culted and was never needed. Maybe it's still useful, you just don't know about the threat thought about by the original developer. We don't know enough to decide. – Z.T. Jul 10 '19 at 21:09

2 Answers2

4

TLS protects the communication between client and server. It is unclear, what specific attack vector this hash is trying to mitigate since not much is known about the application. But if it tries to only mitigate tampering between data between client and server by some malicious attacker then it is not needed with TLS.

It might though that the hash is trying to mitigate manipulation by a "friendly" man in the middle, i.e. one which is explicitly trusted to intercept and manipulate the TLS connection by having its CA imported as trusted in the device. In this case it might make sense to make it more complicate to successfully tamper with the traffic by having some application specific secret to protect the data in addition to TLS.

Steffen Ullrich
  • 184,332
  • 29
  • 363
  • 424
  • hash is on all the fields. and then server does hash on all the fields again. if hash is the same so we assume that data wasnt tempered. Also , replying to your second part , there are no FRIENDLY MITM in our organization. – Royi Namir Jul 10 '19 at 20:40
  • @RoyiNamir: is is less about friendly MITM in your organization and more about some user trying to manipulate a mobile game on its own device or similar. But again, too few details about the actual threat scenario. – Steffen Ullrich Jul 10 '19 at 20:50
0

Without knowing more about your threat model, it's hard to answer this question. However, I want to make a few notes:

  1. TLS (as SSL is known these days) will only protect you from people in the middle who cannot compromise your source of trust. Certificate authorities are by and large trustworthy, but there have been some notable exceptions in the past. And in some countries, the governments forcibly insert themselves as sources of trust, meaning they can freely modify and see the 'encrypted' data as they see fit.
  2. If you use this scheme, you may be vulnerable to a variant of HTTP parameter pollution, where e.g. the part of your code that validates the hash looks at the first instance of a key, and the part that uses it looks at the second. This is rarer these days, but still possible.
  3. Instead of rolling your own crypto with this system, why not use something accepted and common, like authenticatedly encrypting the entire message? Or, if that's too much of a resource burden for your server, you could sign the entire message. Specifically:

    1. Generate the message body as normal, without your hash. For example, let's say your message is the JSON blob {"query":"latest","pageSize":20}.
    2. Using your secret key in your app, sign the message. Now you have a binary blob that is your signature. Let's say the signature is (hex) 18B4EF41. So now you have your signature and your cleartext message. Signatures produced by the same algorithm are always the same length -- in this fictional case, eight characters.
    3. Append the message to the signature. Now you have 18B4EF41{"query":"latest","pageSize":20}.
    4. Send that to your server.
    5. Your server receives it. It knows the fixed length of the signature, so it knows to extract the first eight characters. Now it knows the signature, 18B4EF41, and the message, {"query":"latest","pageSize":20}
    6. Your server uses the same secret to validate that the message is really the exact same one that was sent.

    In contrast, with your solution, you have no idea if the message is the same. All you know is that the specific fields you validated are probably the same. So, for example, you might actually get {"pageSize":20,"query":"latest"}. Or, more maliciously, {"query":"latest","pageSize":20","action":"delete"}. Even if you make sure to validate the lack of a field's presence, there are still a ton of attacks you open yourself up to by only validating the fields, and not the message as a whole.

You'd know that, for example, the first 1024 bytes are the signature, and everything after that can be parsed as normal JSON. Both solutions prevent you from accidentally forgetting to include one field in your hash-and-validate scheme, which would either break communication entirely (if it's only forgotten on one side) or make that parameter forgeable to anyone who can break the TLS (if it's forgotten on both, e.g. if it's added significantly after the others).

As a side note, you're mostly correct about SSL stripping. It can't happen to your app if you directly attempt to connect over SSL and don't allow downgrades, which is the default in every networking library I know. It can only happen if you access your endpoint with e.g. http://, and the server tries to redirect you to https://. A MITM can intercept the redirect so you never get it, do the redirect themselves, and basically become the client. The data is sent to you in cleartext over HTTP, not HTTPS, because they're 'stripping' out the encryption. (This also tends to involve editing the webpages so they don't include https:// links.)

Nic
  • 1,806
  • 14
  • 22
  • we are signing the entire message. – Royi Namir Jul 10 '19 at 20:46
  • @RoyiNamir You said you're hashing based on the fields. I'm saying to hash the entire generated message just before it's sent over the wire. Not just the fields; the _whole thing_. – Nic Jul 10 '19 at 20:51
  • This is what we do. we hash all the fields based on a secret key we have in app.how can you hash the whole thing if the whole thing is with hash that you still dont know ? – Royi Namir Jul 10 '19 at 20:53
  • @RoyiNamir Read what I wrote. Generate the entire message _except_ the hash -- for example, if it's JSON, then generate the JSON all the way, until it's ready to be sent. Then sign _that text_, not the fields. What you're (apparently) doing is putting the hash _inside_ the JSON, which means a MITM can manipulate the structure itself without you noticing, and that opens up an avenue of attack. If you hash the _whole thing_, then it can't be modified at all, not even the "irrelevant" bits. – Nic Jul 10 '19 at 20:55
  • I'm sorry Nic. But if I have json and I encrypt that json and store the hash outside the json VS store it in the json , and then SERVER DOES the exact thing , it takes all the fields , without the json and hash them, to check for a match. - I don't see where is the vaurnability. The server knows which field is the hash and doesn't hash it again. In other words what's the diff between : `{a:1,b:2 , hash:hash (a,b)}` vs `{hash :hash (data}), data:{a:1,b:2}}` ?? – Royi Namir Jul 10 '19 at 20:59
  • @RoyiNamir Because in my idea, you aren't hashing `data`'s value, you're hashing the _entire rest of the message_. I updated my answer with a step-by-step explanation, but you can also just look at how literally any other cryptographic signing protocol works. And, ideally, _use one of those solutions_, because that way you don't _have_ to think about whether it's safe or not, you just know it is. – Nic Jul 10 '19 at 21:12
  • @RoyiNamir No, at this point you should really do your own investigation. I've explained it as clear as I'm able to. You'll be able to find better resources for yourself. – Nic Jul 10 '19 at 21:18
  • Thanks for your time.BTW , It's not something new to me. And still after reading your answer , understanding that you say to hash the whole data as a whole , I just want to say that server doesnt care about client. it gets the request , hash ALL fields it gets ( I've said it already - " _Later, the server does the same thing. It reads the fields and run hash_ ") and then checks for a match. so even if you try to add `action:delete` it won't work. But nevermind. – Royi Namir Jul 10 '19 at 21:22