Skip to content

BLOG

4 Firmware Security Best Practices

5 min read
5 min read
5 min read

It’s hard to overemphasize the importance of security when developing firmware for internet-connected devices. Whether it’s hacking a smart lightbulb or deploying ransomware to a digital camera, firmware attacks are indisputably on the rise.

To highlight some security best practices in this respect, we’ll examine a project where we developed a smart fish tank. Although the finished product had a limited feature set, we applied the same principles we do whenever working with internet-connected devices. In this specific case, the device broadcasts an ad-hoc WiFi network. This smart fish tank can then accept WiFi credentials from a mobile app and connect to an existing, internet-enabled network. Additionally, it can register itself with a remote server, as well as send state updates to and receive payloads from the server.

Despite the relatively limited functionality of this product, we ensured that the entire deployment was properly secured, beginning with the device firmware. Below are some of the best practices we implemented during this project that you can also use for the firmware in your internet-connected devices. 

1. Reduce Your Attack Surface 

The smaller the attack surface, the more easily you can sleep at night. Even though our device needed to broadcast a WiFi network and run a Hypertext Transfer Protocol (HTTP) server, we did not need to do those things after the user had configured the device. By intentionally disabling the ad-hoc WiFi network and HTTP server when no longer needed, we ensured that neither of those features could later be used for nefarious purposes during the regular operation of the device.

In addition, after completing the initial configuration step, the mobile app never could communicate directly with the device again. All communications were thus limited to a single WebSocket channel negotiated between the device and the remote server. The mobile app sends all commands and payloads through the remote server and the server forwards that communication to the device. This way, we don’t have to support multiple communication paths on the device and can focus on protecting the single existing channel.

We also reduced the total amount of information stored on the device to ensure that if it fell victim to an attack, a malicious party could only extract limited value from it. Specifically, we architected the application so that no user data would be stored locally on the device. The only data stored in such a manner are the WiFi credentials and a separate token. The former allows the device to reconnect automatically to WiFi after being rebooted, and the latter allows the device to send data to the remote server. And of course, both are encrypted. As we are fond of saying, “keep the edges dumb” wherever possible.

2. No Plain Text 

This point cannot be overstated. Do not store sensitive information in plain text. Anywhere. Ever. Even though we store potentially sensitive data on our devices, we make sure it is encrypted before storage in the device’s memory. 

As mentioned previously, we allowed the device to receive user information from a mobile app during device configuration. The device then forwards that data on to the remote server and does not retain a local copy. We do this to ensure that the device, when registered with the remote server, is properly authenticated. To protect this data in transit, however, the system encrypts it using a JSON Web Token before it is sent to the device and which is only decrypted after it has been passed to the remote server. This way we can ensure that sensitive user data is never exposed on the device itself.

This principle also applies to communications between devices. When possible, always communicate over secure channels. WebSocket Secure (WSS) or HTTP Secure (HTTPS) for web traffic and MQTT over TLS for machine-to-machine communications are the best options. Depending on the IoT hardware design restrictions, however, it can be difficult to implement secure communication protocols. Insecure channels are not inherently bad (and can be desirable from a cost perspective), but the key point remains: do not send or store sensitive information via unencrypted methods. 

3. Search for Potential Vulnerabilities 

In addition to architecting your IoT deployment securely, you should actively scan for vulnerabilities in device firmware. This is especially true when an area of code may be problematic, such as wherever user input is accepted. Similarly, it is critical to validate data prior to storage to ensure it is not corrupted and capable of causing a buffer overflow or other malfunction.

It is possible to write automated tests or employ commercial and open source scanning tools to check for obvious vulnerabilities, and you should have a well-developed program for doing so. Additionally, you should institute a standardized peer code review program to ensure that developers check each others’ submissions prior to merging and deployment. Finally, you should conduct regular penetration tests against your firmware to identify flaws automated tools might miss.

With all of this said, however, one cannot reasonably expect to identify all potential vulnerabilities during design or development. That makes it especially important to… 

4. Allow for Updates 

No matter how well thought-out a secure design and implementation may seem, there are likely to be flaws in it. No system is perfect. Thus, it is important to be able to fix vulnerabilities before attackers can exploit them. Over-the-air firmware updates are a great solution for addressing security bugs discovered after a product has shipped. Whatever the case, make sure you have a clear and realistic plan for patching devices throughout your deployment that aligns with your cyber risk management goals.

In Conclusion 

The IoT development process can sometimes feel like the wild west. But it is possible to develop networks of connected devices with security in mind. An important starting point is with the device itself, and you can mitigate a lot of problems up front by following four simple best practices: reduce your attack surface as much as possible; don’t store sensitive data in plain text, examine your firmware code for vulnerabilities, and allow for remote updates to it to fix security bugs.

The importance of security extends beyond the device and its firmware, however. For a more detailed discussion of best practices throughout the realm of IoT, read our comprehensive guide to IoT security.