he Voting Machine Village, round two, took place at DEFCON this past weekend.
As I write this at the end of 2017, I think it's safe to say this year was the year of the breach. Major privacy breaches achieved public notoriety. Huge corporations realized that trusting supply chain is actually a real problem...
We're starting to see Bluetooth Low Energy (BLE) show up everywhere. Fitness trackers, IoT doohickeys, deadbolt locks and even security tokens are showing up with BLE. By treating your cell phone as the center of life, things have never been more convenient.
A recent project led to spelunking through a proprietary RTOS built for an embedded device. The engineers who worked on this project were quite bright. There was extensive use of dlmalloc, in the form of the verison embedded in Newlib.
Devices that provide 'local' APIs (i.e. services exposed to the local network) tend to be a lot easier to exploit. A buffer overflow here. A command injection there. Pre-authorization exploits abound! But, devices that only listen to external services for commands tend to be harder targets.
Sometimes you just want to verify that the user has a secret. A secret comes in many forms - a key, a random value, a secret function. How could we verify a user has a secret without building a heavy, cryptographically secure channel?
Most cryptosystems rely on access to true random data. For public key schemes like RSA, you need to generate two random primes to generate your keys. Let's look at how hard it can be to generate real random numbers.
Do you need a full-fledged, pre-emptive multitasking operating system? Will a simple RTOS do the job? Let's look at where the wrong tool has been used for the job.
Dynamic allocation will always undermine determinism and performance of a system. True real time systems will always operate on fixed bounds for every aspect of the system. What are some approaches to simplify memory management?
Firmware is made up of many layers. These are obvious: a bootloader, an RTOS, your application(s), etc. At startup you want to be able to guarantee the integrity of all that code.
We've discussed why you don't fix IVs for AES-CBC. We've touched on the limitations of only using symmetric keys in your application. We've even covered the challenges of protecting symmetric keys. But one sin we have not discussed is fixing your keys.
Public Key Cryptography simplifies authentication. We can use a public key to authenticate firmware updates signed with the private key. Everything seems pretty clear at this point. But we need to keep our keys secure! How can we approach that...
So we stole the keys to the castle, now what? Let's look at how we can take the key and IV we've extracted for our device to decrypt the payloads. Then we can start reverse engineering the communication protocol used by the device.
It seems that Pokemon Go has taken the world by storm. Let's zero in on the issue of application capabilities, or permissions in Android parlance. And let's talk about asking for too much of the user.
IoT devices are resource constrained. Oftentimes vendors will go to great lengths to avoid using TCP. This is not a bad decision on its own: UDP is stateless. But that means you're rolling your own resiliency in.
Now that we know how the firmware is loaded, it's time to look at what the firmware looks like. For this attack to work, we need to be able to load our own code. Ideally, the device will continue to function as it was intended. How hard will this be?
But before we attack the firmware, we need more information. Let's look at how control software interacts with the device.