Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Update Security #9

Open
dbrgn opened this issue Nov 17, 2015 · 16 comments · May be fixed by #98
Open

Implement Update Security #9

dbrgn opened this issue Nov 17, 2015 · 16 comments · May be fixed by #98
Assignees
Milestone

Comments

@dbrgn
Copy link
Collaborator

dbrgn commented Nov 17, 2015

I'd propose to add a way to secure the sensor endpoints using a HMAC-SHA256 over the value, with a single shared secret for the Space API server instance and all clients.

value = 3
mac = hmac_sha256(value, secret)
send_request(data={'value': value, 'mac': mac})

Advantages

  • You can only create a request if you know the secret.
  • Easy to manage because there's just one secret.
  • The message integrity is guaranteed.

Disadvantages

  • Vulnerable to replay attacks
  • Secret is shared between all sensors.

Alternatives

  • TLS, but that's too heavy for embedded devices.
  • A secret per sensor, but that's a bit more complicated to set up. Not too much though, I actually think this might be a good idea. It doesn't solve the replay issue though.
  • Use a one-time session ID that can be requested from the server (challenge-response). It's a bit more complex because it requires 2 requests instead of 1, but might be worth the effort.

I'd like to implement this, but would be happy about feedback :)

@dbrgn dbrgn self-assigned this Nov 17, 2015
@dbrgn
Copy link
Collaborator Author

dbrgn commented Nov 17, 2015

This is a scenario based on a session token:

> POST /sensors/<data_key>/sessions/
< 201 CREATED abcdr4nd0m
> PUT /sensors/<data_key> value=3 token=abcdr4nd0m mac=hmac_sha256('3,abcdr4nd0m', secret)
< 204 NO CONTENT

A token can only be used once. This way we prevent replay attacks and ensure authenticity as well as integrity. The server needs to keep track of active tokens (they could expire as well after 1 minute), but doesn't need to associate a client with a token/session, because the client includes the token in the response.

@dns2utf8
Copy link
Contributor

I like it

@dbrgn
Copy link
Collaborator Author

dbrgn commented Nov 18, 2015

I'll implement the session token version, with a secret key per sensor.

At least at first, the active session tokens will be stored in shared memory. We might still add persistence later on.

@dns2utf8
Copy link
Contributor

Where is are the secret keys stored? We could save them into a DB and create a small script to Insert, Update and Delete the

SecretKey{ sensorName : String, secret : String }

@dbrgn
Copy link
Collaborator Author

dbrgn commented Nov 18, 2015

After some additional thought, I think we should use Redis to implement this. Blocked by #10.

@dns2utf8
Copy link
Contributor

How is the Server authenticated? With TLS the client can store/pin the Server certificate. Should the Server sign its response?

@dbrgn
Copy link
Collaborator Author

dbrgn commented Jul 23, 2016

TLS pinning is a bit of a problem, because each time the certificate changes (at least once a year) the firmware needs to be re-flashed. And some devices might not even have enough memory for one 3072 or 4096 bit TLS key.

Using the session tokens and HMAC approach, the server is not authenticated, you're right. But I don't think that's a problem. We're sending plain numbers, which aren't sensitive. Important is authenticating clients, not servers :)

@dns2utf8
Copy link
Contributor

I think it is good practice to review the infrastructure once per year.

Plus the client can store a 40 Byte sha1 hash, so it does not consume the whole flash.

@dbrgn
Copy link
Collaborator Author

dbrgn commented Jul 24, 2016

It's just additional workoad, that will lead to the counter not working for a while every year without anyone noticing. And I don't think there's any added value in authenticating the server.

@fmorgner
Copy link

I agree @dbrgn in that having to replace the fingerprint once a year will not work out in the long run. Additionally, verifying the fingerprint does not help with authenticating the server (which is kind of unnecessary in the first place).

The ESP8266 TLS implementation does not verify certificate chains, thus verifying the fingerprint is practically useless. It "easy" to create a certificate that matches a certain fingerprint, we would need to verify the common name etc. to get some sort of "trust" going.

I guess @dbrgn is right in saying that we do not need to authenticate the server. The data that is transmitted is not that critical and in addition it is publicly available anyway. Granted, one could do a denial-of-service attack by man-in-the-middleing the connection and dropping the updates, but I believe that this scenario is very unlikely and I am willing to take the risk.

With regard to client authentication, I propose the following idea in addition to what @dbrgn already proposed:

After thinking about it for a night, I believe we could use TOTP. We do not need the clients to keep track of a stable timebase since the server could provide that timebase on request. Granted, that would incur some overhead (in the form of an additional request) but we then could use "industry-standard" technologies. Time is a public factor anyhow, thus i can't see any security issues in having the server provide the timebase on request.

@dbrgn
Copy link
Collaborator Author

dbrgn commented Jul 24, 2016

A MITM (due to missing server auth) could send back a date in the future and then use the TOTP signature for the future measurement to DOS the server later on.

I think implementing the session tokens (used as nonces) is simpler. HMAC-SHA256 is also a standard for authenticated hashing. Here's a library for Arduino that might work on the ESP8266.

@dns2utf8 dns2utf8 modified the milestones: Version 0.3.0, 0.4.0 Sep 1, 2016
@dbrgn
Copy link
Collaborator Author

dbrgn commented Aug 23, 2019

We should also have a way to configure sensor updating:

  • None
  • Without auth
  • With auth

@dbrgn dbrgn linked a pull request Aug 23, 2019 that will close this issue
4 tasks
@dns2utf8
Copy link
Contributor

What is the difference between None and Without auth?

@dbrgn
Copy link
Collaborator Author

dbrgn commented Jan 14, 2020

None means a sensor cannot be updated (in case it's static, or being updated by a script on the server side).

The other two should be clear.

@rnestler
Copy link
Member

With auth

There may be multiple ways to do authentication though, no?

@dbrgn
Copy link
Collaborator Author

dbrgn commented Jan 15, 2020

There may be multiple ways to do authentication though, no?

Yeah, but those don't need to be configured per-sensor, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants