20 March 2018: Isolation vulnerability.
A malicious app can break the isolation between apps and access sensitive data managed by specific apps such as GPG, U2F or Neo.
In order to understand all the work performed by Sergei, it’s important to have an overview of BOLOS architecture.
BOLOS (Ledger’s OS) is a native and versatile OS which can be implemented on several hardware architectures. It uses most of the security features brought by the Secure Element (Nano S case).
The OS lies on the secure hardware and uses the certified security functions implemented in the hardware.
It offers cryptographic primitives which allows applications to compute electronic signatures for instance. To compute an electronic signature the app performs a syscall to BOLOS which takes advantage of the secure hardware to compute securely the digital signature. Furthermore the OS contains certificate allowing to update itself securely. This certificate allows to authenticate the device preventing Ledger devices from being cloned.
It also contains a service which authenticates the applications loaded on top of it. It’s possible to load signed app and unsigned app as well. In this last case a warning is displayed on the screen when launched.
Finally, the OS provides memory isolation. It means for instance that BTC app can not access to the data of the ETH app. This mechanism is enforced using the MPU of the Secure Element.
However, when an app is installed it can derive any key path. So even if the memory isolation is implemented, It’s possible to load an app which can access the private keys of any cryptocurrency. The derived paths during the install can be checked looking at the loading files.
As it’s a bit technical, Ledger strongly recommend to load only signed (by Ledger) app which only derives their own path.
Bypassing the isolation
The security researcher found a bug in our isolation implementation. In several syscalls offered by BOLOS, the pointers the parameters were not correctly checked allowing to reference NULL pointer, or to give pointers located in other regions of the memories. Additionally, in some conditions, the MPU bounds were incorrectly positioned allowing a malicious app to use these syscalls in order to access data outside of its scope.
NULL Pointer dereferencing
The researcher built an oracle allowing to use the Hash primitive to dump part
of memory. The idea is to call
cx_hash_sha256 with a null pointer varying the
length of data to be hashed. The data at offset
0x00 is then hashed by the
cx_hash_sha256 service and the result of the hash is returned.
Secure hash are one-way function but requesting a hash of length 1, allows the attacker to try all possible value for the byte and check which one gives the returned hash. The same process is applied with length 2 knowing the first byte and so on.
- Consequences: it allowed the researcher to dump a large amount of data. The seed and private keys are stored in memory zones that cannot be dumped using this vulnerability.
Pointers length not properly checked
The length of some syscalls (
was not sufficiently checked. Using a malicious applet, it’s possible to use
these syscalls to retrieve partial information. Indeed, depending on the value
RSA_key or of the hash structure header, the crypto service returns a
The attack scenario is the following:
- Load a malicious app which requests one of these crypto service
- The crypto service is called with an incorrect length parameters
- Depending on the value of the pointed memory, a different exception is raised
Consequences: It allows to distinguish some specific value in the memory. In the
RSA case, it’s possible to know if a specific 32-bit value at a given memory
address equals one of these values
0x00020000, or not.
The researcher thought these values were from the RSA key while they belong to the next app.
In the hash case, it’s possible to know if a specific 8-bit value at a given memory address is comprised between 1 and 8.
ecdsa_sign function, it’s possible to retrieve 64 bytes of the memory
of the following application. In this case the implemented mechanism is even
trickier and won’t be detailed here.
In these 3 cases, this is partial information dump but leads at least to an entropy reduction and is thus considered as an attack. Again the seed and private keys remained secure.
After 3 PIN resets, the device wipes the OS data memory, erasing the seed and the private keys which are stored in the OS data memory. But the device does not wipe the apps data. The researcher showed it’s possible to retrieve the data in a previously installed app. The scenario is the following:
- Get a device
- Perform 3 wrong PINs to trigger a wipe
- Install a specific (unsigned) app with a large uninitialized data zone and a command allowing to dump this zone
Consequences: this allowed the researcher to dump memory of already installed app breaking thus the isolation. In our signed applications, secret data are not stored in their flash zone. Only the following applications could have been revealed application data information:
- Neo (a third party app).
- PGP (a developer app). It allows the user to import its private key which is clearly not protected by the seed.
- Monero Beta: this app is only a beta app since it’s released yet. Monero offers different way to handle the key. At the beginning there was no BIP derivation.
- U2F: on this app, the researcher proved it was possible to retrieve the HMAC Key and the current value of the counter of the U2F app.
- The length parameters are now properly checked and the MPU windows correctly positioned.
- The flash user zone is also wiped after 3 wrong PINs. This wipe is checked at startup. The new design is completely tearing proof.
Impact on Ledger devices
A malicious app has to be installed on the Ledger device in order to exploit the vulnerabilities.
If no unsigned application was installed (requiring the use of command-line tools and ignoring a security warning on the device); the data managed by specific apps such as GPG, U2F or Neo is perfectly safe.
Upgrading the firmware fully mitigates the attacks. Firmware from version 1.4 are not vulnerable.
We would like to thank the security researcher Sergei Volokitin who discovered the vulnerability and reported it through our bug bounty program. We also thank him for his good work, his help and his professionalism through the disclosure process.