Securing Embedded Systems

DZone 's Guide to

Securing Embedded Systems

Want to learn more about securing your embedded systems? Click here to learn more about securing bare metals and open and proprietary embedded operating systems.

· Security Zone ·
Free Resource

This article is featured in the new DZone Guide to Security: Defending Your Code. Get your free copy for more insightful articles, industry statistics, and more!

Embedded systems come in a wide range of flavors and can be surprisingly complicated and difficult to secure. I'm going to look at three types of basic designs, describe why they're difficult to secure, and what you can do to secure these systems.

One of the reasons we have so many different kinds of embedded system designs is the wide range of embedded systems people use. We have devices that are considered embedded systems running on hardware ranging from small PIC processors to ARM systems to fully featured systems-on-a-chip, not that different from what we see in cell phones. The scale and feature sets of these chips directly impact the complexity of the controlling software and leads us to a fairly straightforward taxonomy of possible software designs.

One way to look at the kinds of software needed to run these types of devices is to divide the options into categories related to the amount of software you need to write to make the device do, well, whatever it is that you need it to do. Simpler systems may not use any external code, or you may be in a position to write all the code that runs on the device, though this is becoming rarer today as embedded systems become more powerful. Other systems may use third-party open source components, like embedded Linux, or Das U-Boot, or something similar. These kinds of systems are becoming the standard in the Internet of Things space today, as they're easier to manage from a revenue and licensing perspective, they're less expensive to build, and they require less training for engineers to be effective. Finally, we see high-end products using either proprietary or fully featured third-party real-time operating systems. These kinds of systems tend to use software like VxWorks. In these cases, engineers are still responsible for the final system, but the operating system vendor shoulders much of the risk of delivering insecure systems and usually provides extensive support for their products as well. So, let's take a look at these systems to see where the risk lies and how you can deal with it.

Bare Metals

Let's call the first category of systems bare metal, as that's what you're pretty close to when developing on this kind of hardware. In these cases,you're responsible for everything — memory management, peripheral management, thread management, and so on. Fortunately, these kinds of systems are relatively simple, so there's not too much to get hung up on. But trust me, there's enough.

These kinds of programs usually have a single entry point at a well-known memory location (or something similar to this). They also have nothing in the way of pre-existing code. The good news is that nobody else's mistakes may make your system less secure. Unfortunately, that's also the bad news: you take on all the risk. These projects lean very heavily on software development best practices and don't depend on system knowledge at all (as there's really no system in place other than the one you've designed). In order to ameliorate your project risk, you need to implement strong code practices to ensure secure code production (you'll need to do the same for other attributes, like performance and usability, of course). This is pure software engineering practice — you'll need to implement code reviews, understand secure coding practices, use automated analysis tools to ensure appropriate memory handling, and have a clear understanding of your attack surface.

There's a wide variety of secure code auditing tools out there, and two of the most common tools (for the C programming language, at least) areITS4 and RATS. Both of these tools are fairly simple. ITS4 can generate a fair number of false positives, and neither tool will detect design flaws, but they will find things like buffer overflows and race conditions. You will also need to avoid, as much as possible, unsafe standard C library functions.

There's a wide variety of dynamic analysis tools you can use, as well. Valgrind is still one of the strongest dynamic analysis tools available today. Another trick that more experienced engineers will use is to build a set of macros that will allow you to compile your code for x86-based processors. Embedded processors very rarely use the x86 architecture as it's just too expensive for these kinds of applications, so you'll usually be targetingARM or MIPS architectures (or others, like Microchip PIC microcontrollers). Some of these architectures are remarkably different from x86 and may, in fact, use extensions or alterations to the C language (especially for memory management). Being able to compile this code for x86 makes dynamic analysis something you can integrate into your usual build system rather than something you need run on development boards.

Overall, you have the most control over what happens on your system in bare metal configurations. You also have the most responsibility.

Open Embedded Operating Systems

Open embedded options are becoming more and more common today, especially on mass-produced embedded products like smart bulbs or programmable power outlets. And they're becoming more popular for good reason: they're less expensive to distribute, licensing costs are non-existent, they are simple to manage, and they can offload much of the complexity of embedded programming. On these kinds of systems, you can develop your application code in a familiar environment and run that code, in production, in familiar ways. Embedded Linuxes handle all of the more complex system management tasks for you. All you need to do is build and install a couple of userspace programs, usually, one that runs as a daemon process and one or two for system debugging.

Clearly, you're still writing code, so the caveats around developing forbare metal systems still apply. But now you are also responsible for securing the operating system you're using, which can end up requiring a significant amount of know-how.

First, you need to understand the attack surface of the entire system, not just the code you're writing. You also want to minimize this as much as possible. In situations where you have complete control over the code running on the system, this can be significantly easier. When you'reconfiguring a true embedded OS, however, things can get a bit fuzzier. You need to understand exactly what is installed in the OS image you'reusing, and you need to ensure that it only contains services you will need and use.

This means that you need to ensure that SSH is removed, as well as FTP, TELNET, and the like (unless you have a specific reason to include it). You may need to embed some kind of web server, but if you do, you need to know exactly how it works and install the most recent (and hopefully bug-free) version you can. You need to be very deliberate in how you configure the system, and not blindly accept any system defaults. You absolutely need to know how the system works and what all of the components are doing. You are, after all, responsible for the entire product if you use this approach, not just the code you wrote.

Proprietary Embedded Operating Systems

Proprietary embedded systems have the same characteristics as open systems, with some slight twists. To begin with, the operating system and application configuration can be significantly different than what most engineers are familiar with. VxWorks, for example, uses this kind of configuration: the operating system treats application code with the same priority as kernel code, and VxWorks firmware images are distributed as a single binary blob, without the same kinds of familiar file systems and kernel constructs we see in embedded Linux. This makes sense —after all, VxWorks is a real-time OS, and is generally used with non-commodity devices like higher-end industrial and manufacturing equipment.

That said, these kinds of operating systems do have significant advantages. Although they can be more troubling to distribute from a licensing perspective, they generally have much better support, even though you still shoulder the risk from a security perspective. The companies that support these kinds of OSes are large and generally trustworthy (e.g.WindRiver, the company that sells VxWorks, is owned by Intel).

These systems usually have high-quality training available as well. While the same concerns with open OSes exist in these kinds of systems with respect to system hardening, code auditing, and review, you can expect much more support in your efforts to secure your systems.

What Does This Mean for Me?

We've reviewed a taxonomy of embedded systems and covered how you can secure them from an engineering perspective. While it might not capture all the systems you might need to build, it'll cover most of them. So, what should you do?

Well, you'll likely need to make those decisions based on more than securability. The device you're building, the market you're targeting, and your team's expertise are more important drivers in selecting a particular approach. For example, you're not likely to use VxWorks with a commodity IoT device. Likewise, you shouldn't build your own operating system for an expensive real-time programmable logic controller either. With that in mind, these guidelines can help you secure your device no matter the hardware you've chosen.

This article is featured in the new DZone Guide to Security: Defending Your Code. Get your free copy for more insightful articles, industry statistics, and more!

bare metals ,code ,embedded systems ,open embedded systems ,operating systems ,proprietary embedded operating systems ,secure ,security

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}