Breaking a Secured UART with Fault Injection

UART (universal asynchronous receiver-transmitter) is a very common and useful means of debugging a hardware device. It allows for serial communications directly with the underlying firmware or operating system of the device using essentially three wires – transmit (TX), receive (RX), and ground. While it is a powerful tool for device makers to use to troubleshoot or configure a device, it can also be used by attackers to gain unintended low-level access to a system. It will often even have a full unauthenticated root shell listening on it. It is imperative that, if UART needs to be exposed, it is secured to prevent unauthorized access. However, this can prove difficult, if not impossible, as there are many different tricks that can be used to bypass common methods of securing UART. In this post, I will discuss one such trick and how I used it to break a highly secured UART implementation.

Finding UART Pins

The first thing you need to do when you want to talk to UART on a device is figure out where you can connect to the TX and RX pins. Any ground on the board should work fine, but there is usually one that will be grouped next to the TX and RX pins along with a voltage pin, so I usually start by looking for obvious clusters of three or four test pads. On the device I was looking at, there was what appeared to be a footprint for a four-pin connector of some kind off to the side of an EMMC chip that looked interesting to me.

Four-pin connector next to EMMC flash chip

Figuring out which pin is the ground pin is quite easy. You simply use a multimeter to do a continuity test between each one of the pins and a known ground elsewhere on the board, such as a grounded screw, a shield plate, or anywhere the ground plane is exposed. Voltage is equally easy to spot just by looking for a thicker trace coming from one of the pins. Using this method, I determined that pin 1 in the picture above was voltage, and pin 4 was ground. Now, how do we determine which pin is TX and which is RX? The most efficient and reliable way to do so is with an oscilloscope.

An oscilloscope showing a very clear square wave

The TX pin will be transmitting data, so you should be able to see an obvious, erratic square wave pattern coming from that pin, whereas the RX pin will simply be waiting to receive data and would not be transmitting anything. And after attaching the oscilloscope probe to pin 2 of the mystery connector on the device, it immediately showed that it was sending data, making pin 2 the TX pin and pin 3 the RX pin. Now that we’ve found the square wave on the TX pin, we can go a step further to determine the last bit of information needed to connect to the UART pins on the board. Because there is no clock line to synchronize off of with UART, we need to know the baud rate the device is using to properly decode the data. If we focus on the smallest of the pulses in the square wave pattern (indicating a single bit of data), we can measure the amplitude and wavelength to calculate the transmit voltage and frequency respectively.

Measuring a single pulse in the square wave

As you can see in the picture above, the amplitude (ΔY) is around 3.3V, which is a pretty standard operating voltage for UART. And the frequency (1/ΔX) is around 116280 Hz. There are only a handful of standard baud rates that UART operates at, one of which is 115200 Hz, so it is safe to assume that is the baud rate we should try first. Now that we have found the TX, RX, and ground pins and determined the voltage and baud rate, we can use an inexpensive USB to UART adapter board to connect our laptop to those pins (remembering to connect TX on the board to RX on our adapter and vice versa) to communicate directly with the device.

Interrupting Auto-boot

After connecting the USB to UART adapter between my laptop and the UART pins on the board, I was able to power on the device and watch messages scroll by as it ran through its boot up process. Unfortunately, there was not a shell prompt or anything else interactive waiting for me at the end, so I needed to get more creative. The next thing to try would be to interrupt the auto-boot process. Normally, this can be accomplished by hitting ^C or ^D or some other key combination at the right time. Some bootloaders even have a period of a few seconds during which they will prompt users to “hit any key to stop auto-boot". Doing so will halt the boot up process and drop the user into an interactive shell of some kind, usually a bootloader config interface that would allow us to modify the boot params of the device. At that point, we could change the boot process to tell the device to, instead of running whatever script it runs at the end of boot up, simply run /bin/sh or similar to give us an interactive shell. Unfortunately, on this device none of that worked either and examining the messages early in the boot process showed why.

UART output showing boot messages, specifically bootdelay and bootstopkeysha256

As you can see, there is an environment variable called “bootdelay” that is set to -3. The boot delay is the time during which you can interrupt the auto-boot by hitting the right key. Since it is set to -3, that means there is no time allowed to interrupt it at all. Usually, a value like this would be set to 0 to disable boot interrupt, but I think the device manufacturer set it to -3 as an extra precaution against another trick where you just send a flood of data to the RX pin constantly to still catch the boot interrupt. And to make matters worse, there is a variable called “bootstopkeysha256”, indicating that even if we did somehow manage to halt the boot, we would be prompted for a password before gaining access to the bootloader config shell. This isn’t too much of an obstacle, since they also output the hash of the password, and it was easily crackable (password12345), but it is further indication that the UART on this device has indeed been significantly locked down. There was one trick left to try however – ground faulting the EMMC to prevent the system from being able to load properly. In a process popularized by Brad Dixon of Carve Systems, it is possible to cause the firmware of the device to fail to load by pulling the data0 pin of the EMMC to ground temporarily during the right timeframe. This would cause the auto-boot to fail and fall back into the bootloader shell. After once again using the oscilloscope, this time on the pins surrounding the EMMC, I was able to determine that the data0 pin for the EMMC on this device was reachable via the bank of pins near the top left side of the EMMC (seen in the picture above, specifically the pin closest to the “A” silkscreen marking). However, once again this device did not make things easy. There are many points during the boot up process when the contents of the EMMC are checked and validated, and if those validation checks fail, the device does not fall back to a bootloader shell but rather halts completely, requiring a reboot. It starts by doing shmoo plot validation on the EMMC as a whole to make sure it is functional. Then there are several points where files, such as encryption certs, are read and subsequently checked to make sure they exist. If any of these steps do not succeed, the system gives the message “ERROR ### Please RESET the board ###” and does not execute any further instructions. But after examining the boot messages carefully, there appeared to be a very brief window of time between when those checks were completed and when the device tries to load the system kernel from the EMMC.

Getting Serious

Hooking up the UART TX pin and EMMC data0 pin to a DS1180A

If I managed to ground fault the data0 line of the EMMC during that specific span of time, the validation checks will have all passed successfully, but it would be unable to load its operating system which would cause us to fail back to the bootloader config. Getting the timing just right was a bit tricky. Luckily, Keysight has equipment specifically designed for doing just this, namely the DS1180A. Using this tool allows for the monitoring of messages coming from the UART of the device and triggering the ground fault of the EMMC based on the message seen. So when a particular phrase is seen in the boot messages, it will automatically glitch the data0 line with fully adjustable timing. Using this method, we were able to determine that the operative window of time during which the glitch would successfully halt the auto-boot process without causing the system to freeze completely was approximately four seconds, which is actually a lifetime in the world of fault injection where glitches often need to occur in the nanoseconds between individual instructions. And finally, after having to jump through many, many hoops, I managed to successfully halt the auto-boot process despite how locked down the UART interface was.


Interrupted auto-boot process prompting for bootloader password

limit
3