Closed th0mas closed 4 years ago
@th0mas thanks for opening this issue. I'm totally for feature flags in principal. Great that you're thinking ahead. π
My only question/concern is from a security perspective: "How will a malicious user abuse the feature flags?"
We've always got to consider these questions from a Red Team
angle;
Will this help us improve security or help "them" attack us?
If all features are baked into the firmware, does that make it easier for a malicious person to crack it? If they gain access to the
UART
interface and it's just a matter of flipping bits in the firmware in order to enable certain features, have we just made the hackers life easier by leaving the feature in the firmware but "disabled" by a flag? We are definitely going to benefit from the fact that fewer people know how to interpret/manipulate BEAM bytecode, but we still cannot take it for granted that it cannot be done. From reading https://stackoverflow.com/questions/587996/erlang-beam-bytecode and related links, it appears fairly straightforward. And since all our code will be Open Source on principal, we will be making the attacker's life quite easy as they will be able to run the exact code on their test bench in the comfort of their home/lab. They can create an offline attack and just bring the crack/script with them to @home where they will let themselves in pretty quickly. π
My preferred approach would be a modular one where we end up with separate firmwares. For example, for the "server closet" (which I would still like to use an electronic lock so I don't have to carry a physical key) I want to have the absolute bare minimum code/firmware because it's the highest "stakes" lock in the building.
If a particular piece of functionality is common to every firmware bundle it goes in the "core".
If a feature/function is not core but is reusable, it becomes an independent module with docs and tests.
(we can use git
modules in our mix.exs > deps
for now, no need for Hex.pm)
If a feature is specific to a particular device, it can be included just in that device's codebase.
LMK if this answers your question or if you need anything else. π
Being able to "flip bits" in the Erlang VM through user (external) input would be a major security flaw in Erlang, so we can be confident this would be patched.
Erlang has only had one overflow vulnerability in 2016: https://www.cvedetails.com/cve/CVE-2016-10253/ so we can presume the BEAM VM is "secure"
I'll look into modularising our existing firmware as there as it is currently very tightly coupled together and it would need refactoring and modularising to implement any of the above strategies.
@th0mas yeah, totally agree. One of the major selling points of Nerves is the Read-only Firmware that dramatically reduces risk of compromise. It would be a pretty sophisticated attack to create an Erlang/BEAM buffer overflow to then execute arbitrary commands and our little system would definitely not be the biggest target. More like some random Telco, Bank or "Crypto Trading" platform that uses RabbitMQ as the message bus.
With that in mind and given that it's actually cheaper to use a 16GB
Micro SD card than a 1Gb
(or smaller if you can still find one) for storing the Firmware image on the RPI. I'm not particularly concerned about the size of the Firmware provided it stays reasonable. (I don't think we will go over 100mb even if we put the proverbial kitchen sink in there!)
Perhaps a pertinent question regarding the feature flags is:
How many types of device are envisioning?
if
we are only going to have 2 types of door, one that requires a 2FA
and the other that doesn't,
then
we can have a single firmware with a case
/ cond
/ if
statement enabling the feature for the particular device.
Maybe let's not modularise/refactor until we get to 4 types of device. π It's probably more work than it's worth at this (proof-of-concept) stage.
@th0mas were you thinking of using the same firmware for the Welcome Display...? Does it not make more sense to have that one be as "dumb" as possible and not have any knowledge of the rest of the system?
@nelsonic thats why I opened this issue.
We could either add a "display" flag to our existing firmware, or create a new one.
I agree with the firmware being as "dumb" as possible, the current firmware leaves all the "thinking" up to the hub. But it would need to have some knowledge of the rest of the system as it needs to be able to display contextual information, as described in dwyl/smart-home-security-system#12.
So any display firmware would need to implement a hub client, which is 60% of the current firmware anyway.
I don't see why the Welcome Display would need to send any data back to the hub, however ... if the display will have the PIR sensor https://github.com/dwyl/smart-home-security-system/issues/10#issuecomment-657084897 to detect movement and switch on the screen, then it might be relevant to send that data to the Hub informing the people in the house that "someone" was at the door, even if we don't know exactly who was there. However ... we will have the Video Security System https://github.com/dwyl/home/issues/130 for those kinds of alerts ... π
Can you think of a scenario where we would want to send data from the Welcome Display back to the Hub? Or are you thinking that all communication between devices will just use the same channel and thus all devices should implement it regardless of how "smart" or "dumb" they need to be?
I think that if we follow occam's razor on this, we should just have a single firmware (to rule them all) and have clearly commented feature flags in the codebase making it clear when a feature only applies to a certain node.
I wasn't planning on the Welcome display sending any info back to the hub, but the hub needs to send information to the welcome display, and for that it needs to implement a hub client.
However, getting a display working on any of my dev devices is currently impossible, see https://github.com/dwyl/smart-home-security-system/issues/10#issuecomment-659461627
I can still test on localhost
and then you can test on an RPi3 if you have one?
@th0mas as noted in https://github.com/dwyl/smart-home-security-system/issues/10#issuecomment-659550125,
very happy to send you a RPi3
to add to your collection. π
(just tell us the exact model number so you can avoid as many brick walls as possible)
@nelsonic an RPi3 model A+ would work well :)
I don't think the difference between the A and B makes too much difference to the software, just the A+ has gadget mode
support, making debugging easier.
A micro SD card of any size would also be useful :))
@th0mas OK Cool. order placed. π¦ β
This seems sorted, closing for now
We need to be able to enable some features on some devices and disable them on others - e.g. The welcome display.
To do this we need some sort of feature flag system, I think we have several ways of doing this.
In #2 I implemented a handshake system, we could extend this to toggling features on and off each device. E.g. We could send a keyword list of flags:
[{lock: true}, {display: true}]
to configure the device on startup. This increases our firmware complexity but allows us to have greater flexibility down the line, for example if you want to add a display later thats a checkbox.Compile time flags. We could configure the firmware features using environment variables and only run the necessary parts. This comes with some more complexity when deploying but will result in clearer firmware code. Changing the features of a device will require compiling and pushing a new firmware.
Different firmwares. dwyl/smart-home-security#10 suggests we will have a separate Pi running the display, so we could create and deploy a new firmware. This would reduce filesize but would result in duplicated code, as, for example, we would have to maintain two
HubClient
s. This is the simplest option as there is no configuration to sort out@nelsonic thoughts?