Get up to $90 of BTC for one week only.

Bitcoin boost

Donjon | 05/15/2025

Tangem Genuine Check Bypass on Android Application

We discovered a vulnerability in the Tangem Android application that could allow counterfeit cards to bypass the genuine check — here's how it worked and how it was fixed

Ensuring the authenticity and integrity of hardware wallets is crucial for maintaining user security. Tangem has implemented a genuine check mechanism to verify the authenticity of its cards. However, we discovered a vulnerability in the Tangem Android application that could compromise this security feature. In this article, we will explore their genuine check process, examine the identified vulnerability, and discuss how Tangem promptly addressed the issue to protect their users.

All findings have been disclosed responsibly with a delay of 90 days to ensure users are not impacted, but it is essential to update the Tangem Android app to the version 5.18.3 or higher if not done already.

What is a Genuine Check?

A genuine check on a hardware wallet is a process that verifies the authenticity of the device and ensures it has not been tampered with. This process typically involves generating a key pair within the device during manufacturing and signing the public key with a certificate authority.

The private key, which remains securely within the device, can then be used to sign any challenge (random bytes). The resulting signature can be verified using the device’s public key. Once the signature is confirmed, the public key’s signature can be cross-checked against the certificate authority to validate its authenticity.

If an attacker attempts to create a malicious or counterfeit device, they would need to sign the generated public key with the certificate authority, which they do not have access to. Consequently, the device would be flagged as non-genuine.

It is crucial to ensure that the device’s private key is highly protected by storing and using it in a secure way. If this key is compromised, it would allow anyone to create counterfeit or malicious devices that could pass the genuine check.

How does Tangem Genuine Check Work?

As previously mentioned, each Tangem card is provisioned with a unique key pair to verify its authenticity. When the Tangem application needs to confirm that a card is genuine, it follows these steps:

  1. The application sends a 16-byte challenge to the card.
  2. The card generates a salt and sign the challenge || salt using its private key.
  3. The card responds with a salt and a signature.
  4. The application verifies the signature by concatenating the challenge and the salt (and additional information if other cards are linked).
  5. The application requests verification from https://verify.tangem.com/card/verify-and-get-info using the card ID and public key.
  6. The server checks if it recognizes the card ID/public key pair and, if valid, sends back the associated certificate.

How a Single Word Mistake May Compromise an Entire Security Feature?

On Android, the Tangem application performs the genuine check using the Tangem Android SDK. The SDK runs an AttestationTask which follows the process described previously.

However, if the card key attestation step fails (e.g., the provided signature is invalid), the card public key online verification is still performed. The issue is that only the result of this last step is used to attest the genuineness of the card.

This happens for the following reason:

  1. In AttestationTask.attestCard, when the card key attestation fails, Attestation.Status.Failed is set inside currentAttestationStatus and AttestationTask.continueAttestation is called:
if (result.error is TangemSdkError.CardVerificationFailed) {
    currentAttestationStatus = currentAttestationStatus.copy(
        cardKeyAttestation = Attestation.Status.Failed,
    )
    continueAttestation(session, callback)
}
  1. AttestationTask.continueAttestation runs the online verification by calling AttestationTask.runOnlineAttestation and then calls AttestationTask.waitForOnlineAndComplete.
  1. AttestationTask.runOnlineAttestation incorrectly checks if the card key attestation failed by looking at the value of card.attestation.cardKeyAttestation. However, only currentAttestationStatus has been updated. So this method runs the online attestation (which is valid if the given card ID/public key are valid):
val isAttestationFailed = card.attestation.cardKeyAttestation == Attestation.Status.Failed
if (isDevelopmentCard || isAttestationFailed) { // We won't go in this statement
    onlineAttestationChannel.send(CompletionResult.Failure(TangemSdkError.CardVerificationFailed()))
    return@launch
}
when (val result = onlineCardVerifier.getCardInfo(card.cardId, card.cardPublicKey)) {
    [...]
}
  1. AttestationTask.waitForOnlineAndComplete checks the result of the online verification and overwrites currentAttestationStatus (previously set to Attestation.Status.Failed) with Attestation.Status.Verified if the online verification succeeds:
is CompletionResult.Success -> {
    // We assume, that card verified, because we skip online attestation for dev cards and cards that failed keys attestation
    currentAttestationStatus = currentAttestationStatus.copy(
        cardKeyAttestation = Attestation.Status.Verified,
    )
    trustedCardsRepo.append(session.environment.card!!.cardPublicKey, currentAttestationStatus)
    processAttestationReport(session, callback)
}

This means that a successful online check only requires a valid card ID and public key. And it is enough for a device to appear genuine.

How can it be exploited?

A real-world scenario could involve a malicious actor attempting to sell counterfeit Tangem cards that are either pre-seeded with specific data or backdoored (for example, by embedding a specific APDU to extract the key).

To achieve this, the malicious actor could:

  1. Purchase a genuine Tangem card and retrieve the card ID and card public key by intercepting the APDU commands, hooking into the SDK, or analyzing web requests.
  2. Create a counterfeit card that mimics a genuine Tangem card by implementing the same API/APDUs. This counterfeit card must send a genuine card ID and card public key, even if the associated private key is not known. When an AttestCardKeyCommand is received, the malicious card should respond with an invalid signature.

By doing this, the counterfeit card would appear as genuine to the Tangem Android application. However, additional features would also need to be manipulated. For example, during the onboarding process (which involves backing up the master keys on one or two more cards), the cards mutually verify their authenticity in an offline manner. Since the phone acts only as a relay during this process, malicious cards can implement any protocol they want for backup without considering the provided certificates/signatures.

Below is a demonstration of a counterfeit Tangem card implementation that is backdoored to allow extraction of the master key afterward. The final step (not shown in the video) would be to make this card visually indistinguishable from a real Tangem card.

Remediation

November 27, 2024

The vulnerability has been reported to Tangem through their bug bounty program. Tangem promptly acknowledged the report and initiated an analysis on the same day.

November 28, 2024

To address the vulnerability, commit 24588188fdb51ed469cd59d2c595128c1fe63b07 was made, updating the code to check the current attestation status using currentAttestationStatus instead of card.attestation.

This fix has been introduced in the Android application starting from version 5.18.3, deployed the same day.

December 2, 2024

Tangem confirmed the findings and the successful implementation and deployment of the fix. They awarded us a bounty of $15,000 in recognition of our contribution.

February 26, 2025

Tangem explained that the fix was still being rolled out, with 30% of users yet to update their app. Consequently, we decided to postpone the public disclosure until more users had received the update.

April 7, 2025

In light of the vulnerability, Tangem published a blog post detailing significant improvements in their mobile applications.

Conclusion

This case serves as a good example of how business logic flaws can introduce significant vulnerabilities. Often, it is not the highly complex and technical vulnerabilities that pose the greatest risk, but rather the subtle issues rooted in business logic. These types of vulnerabilities can be particularly challenging to identify because they are not easily detected by automated security tools.

To mitigate such risks, it is crucial to conduct code reviews and adhere to secure design principles. Automated testing is also very important, even for security features. These practices help ensure that potential business logic vulnerabilities are identified and addressed early in the development process.

We would also like to extend our gratitude to the Tangem team for their prompt response and effective resolution of the vulnerability.


Baptistin Boilot
With much help from Francisco Freitas and Vincent Bouzon

Security Engineers

Stay in touch

Announcements can be found in our blog. Press contact:
[email protected]

Subscribe to our
newsletter

New coins supported, blog updates and exclusive offers directly in your inbox


Your email address will only be used to send you our newsletter, as well as updates and offers. You can unsubscribe at any time using the link included in the newsletter. Learn more about how we manage your data and your rights.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.