2

I'm developing an embedded application that delivers information through HTTP to my web server. These deliveries are secured by a hash

H(secret : data : nonce)

where the secret is shared between the two entities and the data is the data that is delivered. The nonce is for protecting against replay attacks.

My problem is that the embedded device has no idea of the current time and I can't store any data on it. So on every restart of the device the nonce starts at 1, which isn't very good.

I'm thinking of using a counter as the nonce and then asking the web server on every startup what the last used nonce was and use that as a starting point. In my head this sounds secure since the nonce is no secret, i.e. there's no point in not telling the world about it. But are there any security implications I've overlooked?

4

First things first. Your "hash" is actually a MAC, and a poor one because it fails to ensure security with usual hash functions (SHA-1, SHA-256...). Lookup the length extension attack for details. Basically, if you want a MAC then use a proper MAC, e.g. HMAC. Each HMAC call requires a couple invocations of the underlying hash function, one of them being on short input, so this should be acceptable for your device.

Assuming a proper MAC, you must consider what the nonce is for. The nonce protects against replay attacks only as long as:

  • The server checks that the nonce value is what it expects (equivalently, the server recomputes the MAC by using its known nonce value, and the MAC will match only if that nonce is the same one as the one used in the device).
  • The nonce values are not predictable.

Normal dynamics are the following:

  • Client connects to the server with some sort of connection.
  • Server sends back a newly generated nonce value.
  • Client computes the MAC and sends back the data and associated MAC value to the server.
  • Server checks the MAC value.

In HTTP context, this means a couple of requests. Nominally, HTTP requests are independent from each other, and thus they may happen to appear on the same connection (with "keep-alive"), or use distinct connections; on the server side, if load-balancing is used, the requests may go to distinct front-ends. This may make things more difficult for you. The critical point is that the server should accept a given nonce value only once. If a response has been received, using a MAC value computed with a specific nonce, then the nonce is "burnt up" and MUST NOT be accepted again.

Now for the non-predictability: suppose that the nonce value is, say, a counter maintained on the server (using the current time would be equivalent). At some point in time, counter value is C, so the attacker can predict that some time later, it will be C+100 (or C+100000 or whatever). Such an attacker could intercept a connection between the device and the server, and submit the nonce value C+100 to the device. The device, who believes that it talks to the genuine server, will send a data packet containing a correct MAC value for nonce C+100. The attacker records that answers. At a later time, when the server's counter reaches C+100, the attacker masquerades as the device and sends the recorded answer.

Therefore, a predictable nonce allows the attacker to gather a (valid) data packet from the device, and send it to the server at a time of his choosing. The attacker won't be able to forge a purely synthetic data packet, but he can decide when the packet will reach the server. Depending on your exact context, this may or may not be a problem; it is safer, though, to prevent such things to occur at all.

This sums up to the following:

  • It is not a problem to let people know what nonce values you use.
  • BUT each nonce must be used only once. If two clients connect simultaneously, each gets its own nonce.
  • It is much better is nonces are not predictable. Generate a nonce as a sequence of at least 16 bytes with a cryptographically secure PRNG.
  • If your device has enough juice for it, you may want to switch to SSL (i.e. HTTPS). Within the SSL tunnel, the device can simply use Basic Authentication, i.e. show the "secret" as is, because the tunnel is encrypted and properly done SSL ensures that the device is convinced to talk to the right server.

SSL is heavier (not really for CPU, more for network bandwidth and latency: a SSL handshake is two round-trips, and then one more for the request itself) but it is quite great at convincing people about security. Using SSL saves you a lot of effort when it comes to proving to some auditors that you did things correctly. Plus, it gives you confidentiality, which might be a good thing in your case.

2
  • Great answer. Especially about the non-predictability.
    – m__
    Sep 9 '13 at 20:42
  • You may want to elaborate on the CSPRNG for the nonce. Since nonces must be unpredictable, it is not okay to send the seed once at the session start, and expect a sequence of nonces generated from the CSPRNG using that seed (as this defeats the unpredictability). Sep 10 '13 at 6:07

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.