In this post, I’m going to discuss a vulnerability I discovered in Ledgerhardware wallets. The vulnerability arose due to Ledger’s use of a customarchitecture to work around many of the limitations of their Secure Element.

An attacker can exploit this vulnerability to compromise the device before theuser receives it, or to steal private keys from the device physically or, insome scenarios, remotely.

  • Physical access before setup of the seed

    Also known as a “supply chain attack”, this is the focus of this article. Itdoes not require malware on the target computer, nor does it require the userto confirm any transactions. Despite claims otherwise, I have demonstrated thisattack on a real Ledger Nano S. Furthermore, I sent the source code to Ledger afew months ago, so they could reproduce it.

    No support for video.

    As you can tell from the video above, it is trivial to perform a supply chainattack that modifies the generated recovery seed. Since all private keys arederived from the recovery seed, the attacker could steal any funds loaded ontothe device.

  • Physical access after setup

    This is commonly known as an “Evil Maid attack”. This attack would allow youto extract the PIN, recovery seed and any BIP-39 passphrases used, provided thedevice is used at least once after you attack it.

    As before, this does not require malware on the computer, nor does it requirethe user to confirm any transactions. It simply requires an attacker toinstall a custom MCU firmware that can exfiltrate the private keys withoutthe user’s knowledge, next time they use it.

  • Malware (with a hint of social engineering)

    This attack would require the user to update the MCU firmware on an infectedcomputer. This could be achieved by displaying an error message that asks theuser to reconnect the device with the left button held down (to enter the MCUbootloader). Then the malware can update the MCU with malicious code,allowing the malware to take control of the trusted display and confirmationbuttons on the device.

    This attack becomes incredibly lucrative if used when a legitimate firmwareupdate is released, as was the case two weeks ago.

Proof of Concept

If you want to miss out on the fun of building an exploit yourself, you canfind my proof-of-concept onGitHub.

If you follow the instructions there and install it on a Ledger Nano S runningfirmware 1.3.1 or below, you will be able to reenact the attack in the videoabove. However, because this is for educational purposes only, I havedeliberately made the attack slightly less reliable.

A Note on Responsible Disclosure

Before I get to the details of the vulnerability, I would like to make it clearthat I have not been paid a bounty by Ledger because their responsibledisclosure agreement would have prevented me from publishing this technicalreport.

I chose to publish this report in lieu of receiving a bounty from Ledger,mainly because Eric Larchevêque, Ledger’s CEO, made some comments on Redditwhich were fraught with technical inaccuracy. As a result of this I becameconcerned that this vulnerability would not be properly explained to customers.

I discuss my interactions with Ledger at the end of the article.

Background on Hardware Wallets

Cryptocurrencies, such as Bitcoin, use public key cryptography to protectfunds. You can only spend the funds if you have the private key.

This creates an issue for the user as to how they should secure their privatekey. Humans are notoriously terrible at securing secrets and devices; evensecurity experts are not infallible.

To solve this problem, a class of devices called “hardware wallets” have beeninvented. As the name suggests, these are hardware devices that store users’private keys to protect against malware. Many of these devices connect to a PCvia a USB port, but do not reveal the private keys to the PC, much like ahardware security module (HSM).

However, acquiring the private keys is not the only way an attacker can stealyour beloved Bitcoin. An attacker who compromises such a device could simplychange the recipient of the transaction and the amount being spent! If this isdone surreptitiously, many users will be unaware of this attack until it’s fartoo late to recover the funds.

Therefore, any useable hardware wallet really needs the following features,which differentiate it from a dumb HSM

  • A trusted display for visual verification of the transaction information
  • On-device buttons, in order to confirm or deny signing transactions

Hardware wallets need to protect against a wide variety of attacks, including:

  • Remote attacks (when an attacker can steal your private keys through malwareon your computer)
  • Supply chain attacks (when an attacker can modify the device to do BadThings™ before you receive it)
  • Unauthorized physical access (when an attacker can compromise the device ifthey obtain physical access)

We can further divide the last attack vector into two types: theft and “EvilMaid attacks”. If an attacker can steal the device, they have a longer durationof time to perform an attack, and possibly access to expensive lab equipment.However, they may be thwarted by you realizing your device is missing, andmoving your funds to new private keys.

Security features, such as duress passphrases which aren’t stored on thedevice, can prevent the attacker from stealing your funds in this scenariobecause the device simply does not contain the information necessary to recoverthe private keys.

On the other hand, with an “Evil Maid attack”, the attacker might have alimited time to perform the attack, and won’t have an expensive lab at theirdisposal. These attacks can be far more dangerous due to the wide variety ofscenarios they can be employed in:

  • As the name suggests, an “evil maid” could compromise your device while theyclean your hotel room
  • Your device could be taken from you for a short time as you pass throughairport security
  • You might entrust your device to a relative or lawyer

In this disclosure, we will focus primarily on the case of supply chainattacks. That is: whether or not you can trust your hardware wallet when youpurchase it from a reseller or third party. But, as I explain briefly at thebeginning of this article, the methods described here can be applied to theother two attack vectors.

Breaking The Architecture

In September 2014, Ledger released the HW.1. This wallet was based on theST23YT66, a smartcard with USB support. Unfortunately, this design had severelimitations: there was no trusted display or buttons. This made the walletdangerous to use.

Fast forward to July 2016: Ledger announced a new device called the Nano S.Based on the ST31H320 Secure Element, the new product included confirmationbuttons and a trusted display, along with a USB connection.

In November 2017, I decided to take a close look at the security of the Nano S.

While I didn’t get time to take a look at the newer Ledger Blue, it functionsidentically to the Nano S. At the time of writing, no firmware update hasbeen released to fix the vulnerability in the Ledger Blue.

Dual-Chip Architecture

While there is no public datasheet available for theST31H320, a quick look at thedata brief shows thatthis Secure Element does not support displays! In fact, it doesn’t even supportUSB. The only interface it supports is a low-throughput UART.

“What sort of witchcraft is this!?”, I hear you cry.

As it happens, Ledger developed a new architecture to deal with this issue. TheNano S adds a second, non-secure microcontroller(STM32F042K6) whichacts as a proxy for the Secure Element. This processor drives the display,buttons, and USB interface. It interfaces with the Secure Element, which storesthe actual private keys.

From this point onwards, we’ll refer to the ST31 Secure Element as the SE, andthe STM32 microcontroller as the MCU. A diagram of the architecture looks likethis:

TL;DR: The SE can only communicate directly with the MCU. However, the MCUcan communicate with peripherals, on behalf of the SE.

An important feature of the Secure Element is that we can perform cryptographicattestation to determine that it is running genuine Ledger firmware. This isactually a selling point of the Ledger design: in fact, Ledger argues that thissecurity feature is so powerful that Ledger wallets do not requiretamper-resistant packaging(archive.is /archive.org),as described in the leaflet shipped with all devices.

Ledger’s CTO even goes as far as to tell users that it is completely safe topurchase from eBay(archive.is /archive.org).

This brings us to the key problem. While the software on the SE can be attestedto, the MCU is a non-secure chip and (as we show below) its firmware can bereplaced by an attacker.

And herein lies the problem: to achieve Ledger’s security guarantees, the chainof trust must be anchored in the SE. This means that the SE needs to verify thefirmware on the MCU.

Hardware Tampering

While I will focus on software tampering in this article, it’s important tonote that, in the absence of a software vulnerability, you could stillcompromise the device by tampering with hardware.

It is incredibly important to note that, for these devices to be secure at all,you must completely verify the physical hardware.

Since neither the packaging nor the actual device are tamper-evident, it istrivial for an attacker to modify the device. I cannot repeat this enough: ifyou do not verify the physical hardware, it is game over.

You should also verify the hardware whenever someone could have hadunauthorized access to it, otherwise you are vulnerable to Evil Maid attacks.

Ledger providesinstructionsto do this, but I will note two issues with them.

  1. The pictures are of varying quality. Ledger needs to provide highresolution images that display every component clearly.

  2. The reverse of the device is not displayed at all!

    It is essential that you verify the back of the device, especially sincethis is where the JTAG header (a debugging interface) for the MCU resides.

Even if these two issues are resolved, I would question how expensive it is tohave one of the MCUs with additional flash memory, but identical pinout, to bere-labelled as an STM32F042K6.

Nevertheless, while it is important to touch on this topic, hardware tamperingis not required for the attack I will describe in this article.

Verifying MCU Firmware

Let’s assume that you have meticulously checked the hardware and it isdefinitely unmodified. What happens if the attacker simply changes the MCU’sfirmware?

Ledger considered this attack and, to prevent this, the MCU firmware isverified by the SE.

But it turns out that verifying the firmware on a non-secure processor is notso simple. The SE is nothing more than a glorified smart card, which means thatthe only method of communication with the MCU is via a low-throughput UART.With no direct access to the RAM or flash on the MCU, how can the SE verify itsfirmware?

Ledger’s approach was for the SE to ask the MCU to pass over the entirecontents of its flash memory, as detailed below.

At first glance this seems problematic. Basically, we are asking a (possiblycompromised) MCU to prove that it’s running the official Ledger firmware. Butif the MCU is compromised, what stops it from sending over different code –code that it’s not actually running? This is the challenge that Ledgerattempted to tackle.

The theory adopted by Ledger is based on the fact that the MCU has a relativelylimited amount of flash. To run malicious firmware, an attacker would alsoneed to store the official Ledger firmware, so that it can satisfy the SE. ThusLedger’s approach was to make this difficult given the amount of flashavailable.

Specifically, by verifying the entire flash (and filling empty areas withrandom data), Ledger attempted to make it difficult to store malicious code onthe MCU and also pass the MCU verification.

This is a remarkable idea, and perhaps it’s possible to get it right. However,I was completely unconvinced by this solution.

Mode of Attack

While there are a few obvious methods to attack this design, such as supplyingthe malicious code via USB from an attached PC, it’s much more fun to attempt aself-contained exploit (such as one that could be employed in a supply chainattack).

The method I chose was to “compress” the code. To use a compression algorithmsuch as DEFLATE or LZMA would be impossible due to the trade-offs betweenexecution time, memory usage and code size. A user might notice if it tooktwenty seconds to start up their wallet!

Not to mention, while there were promising results compressing the entireflash, that was not the case for only the MCU firmware – and I did not want toreplace the MCU bootloader, which is also present in flash. This is becausethere are two methods to install new firmware on the device:

  1. Using the JTAG, a debugging interface used by embedded firmware developersto, amongst other things, upload new firmware.

  2. Using the bootloader, which is the method used by Ledger users to installfirmware updates. You can find the Python tool provided by Ledger to dothis on GitHub.

    I was using this method because I don’t enjoy soldering things. If I made amistake while flashing the new bootloader, this method would stop working andthe device would be bricked unless I used the JTAG interface.

Therefore, replacing the bootloader isn’t an option and we have to rule outcompression.

But there’s another approach. When you compile a C program, the toolchain (thesuite of software that compiles programs) will perform a number of magic tricksto make everything work. For example, many processors don’t have instructionsto divide very large numbers. The compiler works around this by inserting asoftware implementation of the division operation. Another example is when youdeclare initial values for variables defined in functions. When the function iscalled, the compiler will insert extra code at the beginning to copy this dataonto the stack.

The extra functions the compiler inserts to perform these tasks are called“compiler intrinsics”. Since the MCU has both a bootloader and firmware, andthese are completely separate programs, these intrinsics will appear twice onthe flash (once in each program).

The upshot of this is that we can insert our malicious routines in place of oneredundant copy of the compiler intriniscs routines (specifically, the copy inthe firmware). This leaves us with an intact copy of that code in thebootloader.

Because the intrinsic in the bootloader is identical to that in the firmware,when the SE asks the MCU for its flash contents, we can “piece together” acorrect image by snipping out the malicious code and instead sending it thecode from the bootloader. When the firmware needs to use the intrinsic, we canjump to the intrinsic in the bootloader instead.

If you’re playing along at home, after building the bootloader and firmwarefrom source code, youcan use this command to find symbols to target

nm -S --size-sort -t d bin/token | grep -i " t "

This command gave me a few interesting symbols that were identical in both thebootloader and firmware. No surprise, all three are compiler intrinsics.

134228637 00000124 T memcpy
134228761 00000140 T memset
134228357 00000266 T __udivsi3

To actually use the malicious code we have hidden, we will have to hook otherfunctions. We do this by inserting branches to our payload in the functions wewant to target. We need to hook the function that sends the flash contents tothe SE, in order to send the bootloader function instead of our malicious code.

I also chose to hook the function that draws to the screen. This allows us todo a variety of fun and exciting tricks. Anything from changing displayedBitcoin addresses and keylogging PINs to, as I will explain shortly,backdooring the private key generation is fair game!

With these two hooks and __udivsi3 as our attack vector, our exploit looks abit like this.

This approach frees up an incredible 258 bytes of payload! Well, we’redefinitely going to have to optimize for size, even if we throw memcpy andmemset into the mix.

Making an Exploit

Our payload needs two components:

  1. Code to modify the flash contents being sent to the SE, to trick theverification procedure
  2. An attack such as a keylogger or key generation backdoor

I don’t know about you, but backdoors seem like more fun to me.

Our exploit doesn’t allow us to compromise the SE, so how can we add abackdoor?

Ledger’s SE firmware has a user interface application which is in charge of thedashboard (and Settings). However, it is also used for the onboarding process(where the recovery seed is generated).

If we can modify the user interface, we can change the recovery seed that isgenerated during the onboarding process. This is quite easy since the userinterface is open source and Ledgerallows you (by design!) to install a modified UX application.

Under normal circumstances, the device would display a warning that the “Userinterface is not genuine”, which would be a red flag for any attentive user.

But recall that I promised that I would explain how controlling the display canbackdoor the key generation? The reason this attack works is that we can simplyhide the non-genuine UX warning.

For this demonstration, we’re not going to do anything sophisticated that areal attacker would do, such as generating a random-looking, yet entirelypredictable, recovery seed.

We’re going to do something much more obvious.

diff --git a/src/bolos_ux_onboarding_3_new.c b/src/bolos_ux_onboarding_3_new.c
index ce1849c..b950ae7 100644
--- a/src/bolos_ux_onboarding_3_new.c
+++ b/src/bolos_ux_onboarding_3_new.c
@@ -395,7 +395,7 @@ void screen_onboarding_3_new_init(void) {
 #else

     G_bolos_ux_context.onboarding_kind = BOLOS_UX_ONBOARDING_NEW_24;
-    cx_rng((unsigned char *)G_bolos_ux_context.string_buffer, 32);
+    os_memset(G_bolos_ux_context.string_buffer, 0, 32);
     G_bolos_ux_context.words_buffer_length = bolos_ux_mnemonic_from_data(
         (unsigned char *)G_bolos_ux_context.string_buffer, 32,
         (unsigned char *)G_bolos_ux_context.words_buffer,

If you’re well-versed in C, you’ll note that I’m replacing a syscall to therandom number generator with a function call that sets all the entropy to zero.As you can see in the video at the start, it generates a recovery seed wherethe first 23 words are abandon (the last word is different because it is achecksum).

Since the private keys are derived from the recovery seed, if you control therecovery seed, you control all the Bitcoin addresses generated by the device.

If we put it all together, we get the following attack which I think is reallyneat.

Of course, since the SE believes the MCU is running genuine firmware,attestation still succeeds. And, as I mentioned earlier, no hardware tamperingwas required, which defeats Ledger’s security integrity verification.

Since the attacker controls the trusted display and hardware buttons, it isastonishingly difficult to detect and remove a well-written exploit from thedevice.

Fixing the Attack

The problem with an architectural vulnerability like this is that it ischallenging to fix without changing the architecture.

Ledger has employed multiple mitigations to try and prevent an attacker fromexploiting this vulnerability.

First of all, the MCU firmware has been optimized and rearranged. Specifically,the firmware calls into functions in the bootloader instead of duplicating thefunctions. While this prevents this particular mode of attack, it’s importantto be aware that there are other, more “creative” methods of attack that I knowof, and probably some that I don’t know of.

Secondly, the SE now times the MCU when it asks it to send the flash contents.This is designed to prevent the use of compression algorithms. It is alsosupposed to prevent code being supplied by the computer over USB. I’m not surehow well it succeeds in doing the latter, due to the fact that the code can bekept in RAM.

However, it’s of note that the SE runs at up to 28 MHz yet the “adversary” (theMCU) runs at up to 80 MHz! This throws into question whether a slower chip canaccurately time a faster chip to prevent it from doing extra things, especiallygiven the slow UART communication.

Ledger refused to send me a release candidate, so I haven’t had an opportunityto verify how well these mitigations resolve the issue. But these raise animportant question.

Is it truly possible to use a combination of timing and “difficult to compress”firmware to achieve security in this model?

Building secure systems using this model seems like an incredibly excitingresearch proposition and I think it’s interesting to see companies like Ledgerpushing the envelope on this.

Interaction with Ledger

Prior to the scheduled disclosure of this vulnerability, I had someinteractions with the CEO of Ledger. You can find an archived copy of his maincomment on archive.is andarchive.org,in case it disappears for any reason.

In these comments, the CEO disputes that these attacks are critical. Some ofLedger’s comments are subjective, and others are more factual. Below I discusssome of these comments.

The first claim I would like to address is that the vulnerability requires aset of incredibly unlikely conditions.

The vulnerability reported by Saleem requires physical access to the deviceBEFORE setup of the seed, installing a custom version of the MCU firmware,installing a malware on the target’s computer and have him confirm a veryspecific transaction.

I am puzzled as to where this claim could have originated from. From latercontact with Ledger, I was informed that the CEO had not at all been briefed onthe security vulnerability when they made these comments on Reddit.

As I stated at the beginning of the article, there are three methods to exploitthis vulnerability, none of which require conditions as unlikely as those.

The malware attack vector I mentioned earlier leads nicely onto the next issueI have with Larchevêque’s comment.

Saleem got visibly upset when we didn’t communicate as “critical securityupdate” and decided to share his opinion on the subject.

When you fix a critical security issue, you can take one of two routes.

  • Completely conceal the security fix

    This is an effective method to avoid drawing the attention of black hats (ifyour product is completely closed source, which is the case for Ledger).

    This has the downside that most users will avoid updating, especially if theprocess is very painful to do (as it was in this case).

  • Alert users of a critical security issue and force an update

    This is commonly used for open source products or when the vendor suspects asecurity vulnerability is being used in the wild.

    However, this has the downside that it alerts black hats of the presence ofa vulnerability. Therefore, it is essential that users update immediately togain the “first mover” advantage over a potential attacker.

Ledger chose a flawed method, which takes the worst aspects of both of theseapproaches. By drawing attention to the security fixes in their firmwareupdate, while not alerting users to update, you lose the “first mover”advantage.

This gives black hats sufficient time to determine how to exploit thevulnerability, putting all users at risk of the malware attack vector.

My concerns were proven correct, as I was contacted by multiple independentwhite hats who had determined the issue purely from Ledger’s firmware updateinstructions.

Disclosure Timeline

  • 11 Nov 2017: Officially reported vulnerability to Nicolas Bacca, LedgerCTO. Vulnerability determined to beimplausible.

  • 14 Nov 2017: Demonstrated practical supply chain attack with modified MCUfirmware and user interface. Sent source code to Bacca.

  • 30 Dec 2017: Bricked the Ledger Nano S by downgrading the firmware to anunsupported version. Press F to pay respects.

  • 06 Mar 2018: Ledger released firmware update for Ledger Nano S.

  • 20 Mar 2018: Write-up and proof-of-concept code released.

  • Firmware update for Ledger Blue unreleased at time of writing.

Acknowledgements

I would like to thank Josh Harvey for providingme with a Ledger Nano S, so I could turn my theoretical attack into a practicalexploit.

I would also like to thank MatthewGreen, KennWhite and Josh Harvey for your invaluable helpin editing this article.


https://saleemrashid.com/2018/03/20/breaking-ledger-security-model/?spm=a313e.7916648.0.0.734ccd05LwRcSR