Open heythisisnate opened 1 year ago
This is labeled as ‘won’t do’ - by virtue of the process mitigating the need for storing the token permanently, for security and for simplicity. The reboot failsafe loop is only temporary and corrects itself when a new token is picked up.
Based on the process of homebridge rebooting and subsequently reprovisioning the board with new auth tokens and storing them in the active session.
This is problematic when the Konnected device is rebooting/retrying to update state to HomeBridge, there can be a race condition or timing condition where HomeBridge cannot re-provision Konnected because it's in the process of rebooting/retrying. I'm not sure if HomeBridge continuously retries to send the provisioning request and it will eventually become consistent or not ... but it could take a long time, potentially missing state change events in the downtime.
Homebridge will keep trying to provision the device with the latest settings it has and new auth tokens until the device is available to receive the reprovisioning and handshake of latest states.
We should not be storing authorization tokens outside of the active live session, otherwise we are defeating the purpose of the security strategy of auth tokens in the first place.
From a quick glance this issue also appears to have arose from an unhandled panic of the device firmware when it didn't receive the correct authorization from a call made to it.
That should be handled gracefully with a reported message until it can receive the proper authorization creds, or until it is reprovisioned to use new ones.
I just pushed a firmware fix [https://github.com/konnected-io/konnected-security/releases/tag/v3.1.4] that should partially help. Before this fix, when Homebridge would return a 401 status after the token resets following a reboot, Konnected would crash and reboot immediately instead of gracefully waiting 30 seconds between failsafe boot loops. That's fixed now, and the 30 second delay allows for Homebridge to re-provision with the new credentials.
However, it's still very problematic that Homebridge "forgets" the exchanged auth token between reboots. Konnected is not intended to be re-provisioned over and over again, and leaving it open to do so is a far greater security risk than storing a shared secret within Homebridge. If Homebridge can re-discover and re-provision the Konnected boards at any time, then any device on the network can also do so, allowing a malicious actor on the network to be able to re-provision Konnected to point away from the desired controller, and neutering any security system within Homebridge. We've protected against this by implementing a Lock feature, which can be activated via the Konnected app or device API [https://konnected.readme.io/reference/getlock] which locks-down the device from being re-provisioned. This depends on the expectation that the server/controller IP, port, and shared-secret will not change and cannot be changed without specific authorization from the end-user.
This plugin's assumption that Konnected should be open to regular re-provisioning of network settings/credentials is in direct conflict with the Lock feature and our best practices regarding network security.
FWIW, it seems to be fairly common to store passwords or other secrets in Homebridge's config.json
, and it seems to me much less of a security risk than allowing Konnected to remain open and re-provisionable by any actor.
When you say this:
Konnected is not intended to be re-provisioned over and over again, and leaving it open to do so is a far greater security risk than storing a shared secret within Homebridge.
Let’s not get ahead of ourselves here. The hope is that any platform provisioning the konnected device, and the konnected device itself, are both stable enough to not keep reprovisioning over and over again in the first place. Once provisioned, continue steady operation indefinitely with that current auth token and no others.
Storing the auth token doesn’t resolve problems inherent with instabilities in the system elsewhere (firmware, plugin, homebridge system, networking or otherwise).
Leaving the device open to be provisioned by any actor is at its core a valid setup feature (the security of which is dubious at best, as expected).
But,… you have both made my case for me and instead brought up a better reason for storing the auth token in this:
Konnected should be open to regular re-provisioning of network settings/credentials is in direct conflict with the Lock feature
And if that option is available to the user in the device setup, then I must provide affordance to accommodate that scenario that the user has locked their konnected device at the firmware level and will only work with one auth token from there on out. Not because the device shouldn’t be provisioned with a new token over and over.
And, let’s be clear here, storing the auth token is still as equally a security risk as being able to provision the device by any external actor. If an external actor has gained access to provision the device on the network,… then it’s entirely in question that they can access a platform that has a stored auth token as well – All concerns of which, could be, but aren’t in the scope of this entire project.
Copying this over to my personal repo for triage.
When the HomeBridge plugin provisions a Konnected device, it randomly generates a token that Konnected uses in subsequent requests when contacting the HomeBridge server. The problem is that when HomeBridge reboots, previously generated tokens are not stored persistently and are lost, causing the Konnected device to fail to connected to HomeBridge to post state updates. This may cause Konnected to fall into a reboot/failsafe loop, and HomeBridge may be unable to re-provision the Konnected device in this state.
Proposed solution: Persist generated auth tokens so they survive and remain valid after HomeBridge reboots.