Exploring security vulnerabilities in NFC digital wallets | Cossack Labs

🇺🇦 We stand with Ukraine, and we stand for Ukraine. We offer free assessment and mitigation services to improve Ukrainian companies security resilience.

List of blogposts

Exploring security vulnerabilities in NFC digital wallets

In recent years, we have been reviewing and improving the security of small near-field communication (NFC) devices: smart contactless cards, mobile digital wallets, specialised authentication devices, among others. Some of them are used to sign financial transactions, store secrets, activate other hardware in specialised industrial systems, or verify the user’s identity.

This time, we’ll explore NFC security issues linked to device storage and communication between mobile / web applications. Such devices are versatile and widely used wherever secrets need to be removed from systems.

We’ll also take a look at some other real-world examples that come up in various environments and systems.

nfc security

  1. Why store secrets in NFC devices?
  2. Exploring vulnerabilities in NFC key vault
  3. More wild exploits of NFC devices
  4. Mitigating NFC security risks
  5. Summary: NFC devices security consideration

This blogpost is a part of the “Digital wallet security guides”: Read the articles Crypto wallets security as seen by security engineers, How to prevent digital wallet fraud, Digital payments security architecture guide.

1. Why store secrets in NFC devices? #

NFC tags are small, cheap, and battery-free. They operate within a short distance of the reader in almost any environment and transmit data instantly. Being programmable, they can support cryptography and other complex algorithms, and unlike QR or barcodes they can not be easily cloned.

Since smartphones with NFC readers are widely available, it makes the technology accessible to the general public. In the security context, NFC devices are used in several ways.

NFC cryptocurrency wallets

Cold wallets are used to store keys and sign transactions. Some cold wallets (crypto hardware wallets) are designed like contactless smart cards, others like a USB stick with NFC module.

Firmware activators

Similar to digital keys, NFC devices send encryption keys to decrypt and activate firmware of larger devices, such as industrial machines or unmanned vehicles. Without the corresponding keys these larger devices will not operate. Such systems record who and when activated the device, and in some cases might require two NFC keys (“two-person rule”).

FIDO and FIDO2 tokens

External security keys that store cryptographic keypairs and enable login on websites: either working as a second factor for MFA, or as a single device for passwordless authentication.

Access control devices

NFC-enabled doors or transportation cards combine a key and an ID to function as an authentication factor.

NFC tags for inventory

Electronic shelf labels (ESL) are becoming more common in retail stores. They display the price for a product on an e-ink display, allow wireless price updates and show promotional offers.

Financial transactions and payments

NFC and EMV power contactless payments and are considered to be more secure than magnetic stripe cards which can be copied even with the help of iron filings. From this perspective, magnetic stripe cards are more like “magnetic barcodes”. On the other hand, NFC or EMV have complex multi-round authentication and encryption protocols that prevent secrets from being revealed to the adversary even if they are traced (especially to skimmers).

2. Exploring vulnerabilities in NFC key vault #

In this section, we’ll share some discoveries we’ve made when working with the NFC key vault product. Despite originating from a specific engagement (subject to disclosure limitations for obvious reasons), we’ve seen the same problems before and will likely see the same problems over and over again, hence the post.

Imagine the MIFARE Plus card and mobile app. The card communicates with the app via NFC-A by sending APDU commands. These cards function as a “secure digital wallet”, a cold storage for generating and storing private keys and for signing the provided payload for making contactless payments.

On top of APDU, the authors built a custom communication protocol with encryption. However, during the design process, they made a few missteps and had a slightly misfitting threat model, which led to a number of issues that are useful to consider for future “HSMs with NFC” products. Let’s look at the most intriguing ones first.

hid cossacklabs

Breaking financial transactions made with NFC cards requires many attempts. :) A piece of our lab.

2.1 Replay attacks with NFC cards (active MITM) #

Replay attacks are one of our favourites because they are frequently overlooked in various protocols, particularly those that use encryption. We described these attacks in detail in another post, but in a nutshell, they exploit the ability to send the same commands twice, which can trigger some computations again

This security flaw is serious. Even if a mechanism to prevent a replay attack between multiple sessions is in place, this does not preclude the attack from being carried out during a single communication, or simply in a single message.

Imagine a car that can be locked and unlocked with a wireless key. You can control the car without the owner by intercepting the “unlock” command once, which is easy to do with some inexpensive hardware. This is a classical example of an Authentication Bypass by Capture-Replay attack. You might believe that modern cars are equipped with sophisticated algorithms to prevent such problems, and you’d be almost right.

table of vulnerabilities cossacklabs

Vulnerabilities related to CWE-294

Nonetheless, mounting a replay attack frequently requires an active Man-in-the-Middle (MITM) position to collect messages. While it is difficult to perform MITM during NFC communication because the attacker must be very close for some time, it is not entirely impossible, especially when it comes to payments.

2.2 Passive MITM attacks in NFC #

Traditionally, MITM attacks in NFC communications are considered to be implausible, though research on this topic is underway.

Imagine sitting with your friends in a cafe and showing off your new digital wallet, while an AirTag-like device under the table tries to interfere with NFC communication. Even if conducting an active MITM attack is difficult, passive eavesdropping could pose an issue. You don’t want to send your PIN code in plain text, do you?

A partial mitigation for MITM attacks is encryption. Your digital wallet card and mobile app exchange encryption keys and set up encrypted communication.

Secure and authenticated key exchange is a critical component of cryptography, and it’s quite challenging. One of the traditional approaches is using the elliptic curve Diffie-Hellman algorithm.

ECDH is resistant to passive eavesdroppers but vulnerable to active ones because it lacks authentication. The adversary can open two sessions with the mobile app and the device and effectively re-encrypt the messages back and forth.

There are several ways to achieve authenticity. The NFC card, which we discuss, uses a password for it: the user enters the password on their mobile app, which then communicates with the card, and the card checks the password.

This password is blended into the ECDH in the same way as the pre-shared key is used in TLS: the pre-shared key is used as input to KDF, which derives the shared secret from the shared point.

# Example of INSECURE password-authenticated key exchange
def derive_key(password, salt, alice_private_key, bob_public_key):
    shared_secret = ecdh(alice_private_key, bob_public_key)
    key = pbkdf2_sha256(shared_secret + password, salt, rounds=20)
    return key

The problem with this approach is in the password itself. Passwords are not cryptographic keys because they are not uniform and have low entropy, making them vulnerable to dictionary attacks. Passwords can be brute-forced online if there is no restriction on the number of attempts. Furthermore, the password can be also brute-forced offline by exploiting the protocol using active MITM attacks, which should not be possible if the password-based key exchange is effective (we are looking at you, WPA2).

The moral remains the same: encryption is easy, key exchange is hard.

Use the appropriate mechanisms for your use case, such as CPace or OPAQUE for password based key exchanges; custom PKI like in TLS; trust on first use like in SSH or Signal, and so on. The context determines the requirements, threat vectors, assumptions, and guarantees. It’s a broad subject with no easy answers.

2.3 NFC encryption flaws #

Let’s assume the keys are exchanged, and each message is encrypted with a symmetric key. So the entire user session is protected, isn’t it?

Our NFC card can sign financial transactions using its private key. The mobile app and the device communicate using the APDU commands. The APDU request is a simple message, with the first four bytes serving as a header and the remaining bytes serving as a payload.


The CLA, P1, and P2 are instruction classes and parameters, which are typically constants or just zeros, and thus have little meaning for us. The INS, on the other hand, is an instruction byte that specifies the command’s opcode. The payload consists of a byte array containing encrypted TLV records.

Each TLV record has three fields: Type, Length and Value. The types are unique across the command. For example, if the command requires a hash to sign, it expects only one Type::Hash argument. But what if you provide the second argument?

Our victim NFC card extracted arguments using linear search, so only the first is considered, and the rest are ignored.

Do you see the problems?

Finding cryptography bugs requires specialised knowledge.
Share your concerns and evaluate your solution with our engineers.

2.3.1 INS byte is not encrypted #

Because encryption is only used for the payload, the header, including the instruction byte INS, is not protected. An active adversary can easily change it to generate a new command!

However, creating a valid command is not as simple because the arguments must fit. In that case, we should find the commands whose arguments are compatible:

  • GEN_KEYPAIR(slot)
  • DEL_KEYPAIR(slot)
  • SIGN(slot, data)
  • GET_PUBLIC(slot)

The slot is just the index of a keypair, as the device can support multiple of them. As you can see, almost all keypair-related commands are interoperable! So, even if the arguments are encrypted, a SIGN(slot, data) command can be changed to a DEL_KEYPAIR(slot, data) command just by changing one INS byte.

2.3.2 Arguments are not validated #

As the parser simply “ignores” extra arguments, the data is ignored, and the card successfully processes the DEL_KEYPAIR(slot, data) command, destroying the keys with no recovery mechanism :c

This is a result of unfortunate design decisions in which not all bytes of the command are protected, and parsing issues frequently manifest themselves as security vulnerabilities in the real world.

To prevent this from happening, the header of the APDU must be encrypted too. If it’s not possible, the integrity must be protected by the AEAD, where associated data is the header. Also, improving the parsing process by checking the number of arguments and using only those required for the command is a good idea.

2.4 Timing Attacks #

As a bonus, the “relaxed” parser allowed us to check exploit timing attacks and find “backdoor” commands on the NFC card.

We crafted a list of commands with small and random arguments up to the maximum allowed APDU size for each possible command byte. If the command exists, the card begins a time-consuming linear search for the arguments.

for b in 0..=0xff {
    // ~1000 bytes, ~300 arguments
    let mut apdu = hex!("000000000003e1650117650117650...");

    // Set the instruction byte
    apdu[INS] = b;

    // Measure the response time
    let start = Instant::now();
    let elapsed = start.elapsed().as_nanos();

    // Collect measurements
    println!("${b}, ${elapsed}");

If the command doesn’t exist, the card returns an error. Otherwise, if the command exists, but the arguments are incorrect, the card also returns an error. However, the response time is drastically different, allowing us to scan for undocumented commands.

That means our victim card is vulnerable to enumeration attacks. They exploit some kind of leakage, such as different returned errors in various cases or differences in response time. Enumeration attacks allow scanning of accounts, usernames, or emails in the real world. In the worst-case scenario, this leakage allows recovering secrets such as passwords or keys.

graph cossacklabs

The response time depends on which command is processed by the NFC card. Undocumented commands are discovered by enumerating command bytes and examining response times.

Remediation of these attacks is hard and often impossible. However, the common recommendation is to create different failure paths to respond with a general error. In the best-case scenario, the execution of the successful and error paths should be indistinguishable, but the risk isn’t always worth it. Unless you’re working on a cryptographic library, in which case constant time is essential.

2.5 Cyclic Redundancy Check and Integrity #

As we noticed, the CRC-16 (Cyclic Redundancy Check) integrity check is a popular choice among those attempting to implement encryption on small smart devices. We’ve already discussed it in the ”Cryptographic failures in RF encryption allow stealing robotic devices” post.

In the case described in the post, developers used “encrypt-then-CRC”, but the current NFC card uses “CRC-then-encrypt”. Both options are bad because the CRC should not be used for the integrity check with encryption.

# CRC-then-encrypt example
def encrypt(key, message):
    iv = b'\x00' * 16
    tag = crc16(message)
    plaintext = tag + message
    ciphertext = aes_cbc_encrypt(key, plaintext, iv)
    return ciphertext

The CRC is not designed for cryptographic integrity; it provides only error detection because it contains no secrets: an attacker can change the data and re-calculate the CRC.

The CRC is usually too small (16 or 32 bits, compared to the 96-bit GMAC or the 128-bit Poly1305), leaving a chance to forge the tag. The CRC is malleable, which means that it can be transformed and forged predictably even if encrypted. With such protection an adversary could generate valid ciphertext without knowing the key. Other powerful attacks, such as manipulating or decrypting plaintext, are also possible.

The CRC should not be used for integrity check with encryption, so both options “encrypt-then-CRC” and “CRC-then-encrypt” are flawed.

In addition to the CRC-16, the NFC card uses AES-CBC encryption (yes, with a static iv). Therefore, the card decrypts the command in the following steps: decrypt, strip padding, check the CRC.

Because the padding is stripped first, the card has a chance to fall into a cryptographic doom or play a game with a wise padding oracle.

A better option would be to “encrypt-then-authenticate” using proper MAC, like HMAC, GMAC, or Poly1305.

3. More wild exploits of NFC devices #

Combine NFC, ATMs, and buffer overflows, and you would get one of the most impressive attacks of recent years.

In a nutshell, researcher Josep Rodriguez exploits ATM bugs just by putting his phone over the NFC reader to modify transactions, make the ATM useless, change the dollar price, and even dispense cash!

All of these attacks were possible because of the software flaw. The system didn’t validate or put a limit on the size of the APDU message, so Josep could trigger the required functionality with specially crafted large commands. This and other software bugs are common methods of system exploitation.

NFC cards are quite susceptible for replay and pre-play attacks. Leigh-Anne Galloway and Tim Yunusov describe in their talk First Contact—Vulnerabilities in Contactless Payments how to bypass contactless payments made with physical cards.

Also, we recommend watching NFC Payments: The Art of Relay & Replay Attacks talk by Salvador Mendoza to learn more about the NFC exploits and how to assemble NFC intercepting devices at home.

nfc payments cossacklabs

A picture of designed Proof of Concept from Salvador Mendoza’s blog post

4. Mitigating NFC security risks #

Effective security measures start with proper threat modelling. Consider an NFC device (a card) and an NFC reader (a phone) to be connected “over the wire”, and always available for active and passive MitM.

Plan security measures based on the assumption that both parties could be compromised:

  • data encryption (and / or signing messages)
  • transport encryption,
  • an API that protects against replay attacks.

Next, remember that an NFC device that performs cryptographic computations requires additional specific security controls such as:

  • performing constant-time operations,
  • rotate encryption keys for every session, respecting forward and backward secrecy,
  • encrypting data using modern and strong ciphers (AEAD),
  • not using the CRC as an integrity check 🙂,
  • storing secrets in a secure vault,
  • using unbiased CPRNG,
  • avoiding side channels that may expose secrets.

If the system involves cryptography, talk to cryptographers who can evaluate your requirements and protections. Some encryption protocols may appear to be secure on paper but are insecure in the wild. Sometimes, intercepting only one sent package allows brute-forcing secrets offline and then decrypting all further communication.

The first thing behind system security is its reliability. Of course, any system could be broken, but good security practices reduce the risks by modelling threats, designing architecture, carefully implementing code, testing, auditing, fuzzing, and maintaining, among other things.

Need security engineering assistance with applied cryptography?

5. Summary: NFC devices security considerations #

Widely adopted #

NFC technologies are a dream in many ways: they are small, inexpensive, and battery-free, which seems almost magical. They are particularly popular in security contexts due to their ability to move secrets away from always-connected applications.

NFC devices are widely used in finance as contactless payment cards and cold cryptocurrency wallets; in industry as activation devices and wireless keys, and in everyday transportation trips as authentication devices.

NFC devices are frequently used to breach the systems they were designed to protect.

Vulnerable #

Our research shows that some NFC devices are vulnerable to pre-play, replay, relay, eavesdropping, and side-channel attacks that trick the card to perform an unauthorised action or extract sensitive information.

Cheap #

No matter how small the NFC device is, it can bring into big trouble. The assembly of an NFC intercepting device is simple and inexpensive. Because the device is usually small, attackers can test it without drawing too much attention to themselves.

Complex #

So, when dealing with NFC, it’s crucial to conduct a proper threat modelling. Just remember that incomplete threat models lead to wrong design assumptions, lack of testing—to the firmware bugs and parsing errors, and poor understanding of cryptography—to cryptographic flaws.

If you are building systems that use NFC devices, we recommend that you do a thorough assessment of NFC card vendors and their communication protocols before adding them in your project. This will help you gain a comprehensive understanding of the threats and the implementation of multiple layers of defences. And with proper preparation you can minimise chances of successful exploits.

If you’re struggling with applied security in hardware, communication protocols, digital payments systems or mobile apps, you’re not alone, feel free to drop us a line to get some assistance.

This blogpost is a part of the “Digital wallet security guides”: Read the articles Crypto wallets security as seen by security engineers, How to prevent digital wallet fraud, Digital payments security architecture guide.

Contact us

Get whitepaper

Apply for the position

Our team will review your resume and provide feedback
within 5 business days

Thank you!
We’ve received your request and will respond soon.
Your resume has been sent!
Our team will review your resume and provide feedback
within 5 business days