The Second Factor in the Backup: Reading otpauth URIs Out of ASCII Decimal

Mobile Security Level 2/4 ~3 min October 7, 2026

The challenge

A handset came back at offboarding and the forensics queue pulled an unencrypted application backup off it. Inside, one of the authenticator app's preference files holds a value the developers stored as a run of numbers rather than as text, presumably because it looked less like a secret that way. It is not encrypted and it is not a hash. Three accounts are in there. Recover the shared secret that generates the payroll codes.

What you'll learn

  • Recognise a run of numbers in the 32 to 126 range as ASCII code points
  • Read the fields of an otpauth URI and identify the seed
  • Explain why a leaked TOTP seed is permanent and device-independent
  • Describe how application backups become an exfiltration path for secrets

Skills tested

Encoding recognitionMobile artefact analysisAuthentication reasoning

Prerequisites

  • What a one-time code app does
  • That ASCII maps characters to numbers

How it works

A time-based one-time code is not a secret in itself. It is a function of the current time and a shared seed, computed identically on the phone and on the server. Scanning a setup QR code is how the seed gets onto the device, and the QR encodes an otpauth:// URI whose secret parameter is the seed in base32.

That makes the seed the whole of the second factor. It never changes, it is the same on every device that holds it, and using it leaves no trace distinguishable from the real user. An attacker who copies it does not need the phone again, and the account owner has no way to notice. Recovery means the issuer resetting the enrolment, which almost nobody does after a device is simply handed back.

Storage is where it goes wrong. Seeds belong in the platform keystore, flagged so that they are excluded from device backups. When an app keeps them in ordinary preferences, they travel wherever the backup goes, and writing each character as a decimal number is not protection of any kind: it is the same bytes, spelled differently, readable by anyone who notices the values never exceed 126.

Common mistakes

  • Answering the Corvid Mail or Thornbury VPN seed. All three lines look alike. The label asks for payroll.
  • Submitting the whole URI. The answer is the value of secret, not the line it sits in.
  • Trying base64 or base32 on the input. Neither alphabet contains spaces, and the numbers give away what this is before you touch a button.
  • Expecting a six-digit code. The code changes every thirty seconds. The seed does not, which is why the seed is what matters.

How to defend against it

Keep seeds out of anything that gets copied.

  • Store them in the hardware-backed keystore, with the no-backup flag set. An authenticator that survives a restore to a new phone is one that put your seeds somewhere a backup can reach.
  • Exclude the app's data directory from automatic backups, and test that exclusion rather than trusting the manifest.
  • Re-enrol the second factor at offboarding as a matter of routine. Collecting the handset is not the same as revoking what was on it.
  • Prefer phishing-resistant factors bound to a device, such as a passkey or a hardware key, where the private material cannot be exported at all.

Full solution

Pro and Max members unlock the complete step-by-step walkthrough.

Go Pro

Community stats

205 completions
86% success rate
M2F14M3 First blood

Related Daily Hacks

31,000+ Hackers Real labs Free
Start Hacking Free or solve today's hack, no account needed