This repository contains the paper titled Security and Privacy Failures in Popular 2FA Apps
, which has been accepted to USENIX Security
2023
, and its supplemental materials and artifacts.
The Time-based One-Time Password (TOTP) algorithm is a 2FA method that is widely deployed because of its relatively low implementation costs and purported security benefits over SMS 2FA. However, users of TOTP 2FA apps face a critical usability challenge: maintain access to the secrets stored within the TOTP app, or risk getting locked out of their accounts. To help users avoid this fate, popular TOTP apps implement a wide range of backup mechanisms, each with varying security and privacy implications. In this paper, we define an assessment methodology for conducting systematic security and privacy analyses of the backup and recovery functionality of TOTP apps. We identified all general purpose Android TOTP apps in the Google Play Store with at least 100k installs that implemented a backup mechanism (n = 22). Our findings show that most backup strategies end up placing trust in the same technologies that TOTP 2FA is meant to supersede: passwords, SMS, and email. Many backup implementations shared personal user information with third parties, had serious cryptographic flaws, and/or allowed the app developers to access the TOTP secrets in plaintext. We present our findings and recommend ways to improve the security and privacy of TOTP 2FA app backup mechanisms.
The repo contains the full paper here and the bibtex here.
The artifacts and related instructions in this repo are intended to allow researchers to verify and fully reproduce the findings presented in the paper. The major findings in the paper are documented in Tables 1, 2, and 3:
- Table 1: Overview of the backup mechanisms supported in each app
- Table 2: Overview of the backup mechanisms that automatically sync data to the cloud
- Table 3: Cryptographic details of app backup mechanisms that use encryption
The artifacts available include:
-
Search Terms: The list of search terms that we used to identify as many TOTP apps in the Google Play Store as possible (see Section 4.1 - App Selection).
-
App Checklists: For each app, the customized checklist that enumerates exactly which actions to take within the app and which data to enter while recording the network traffic (see Section 4.2.1 - Exploring the App).
-
Decryption Scripts: For each app that supports encrypted TOTP backups, the golang script that implements the decryption process (see Section 4.2.3 - Performing Cryptanalysis).
The ordered steps below should be followed individually for each app to verify and reproduce the paper's findings.
- Step 1 - Capture and review network traffic for each app (Section 4.2.2)
- Step 2 - Review cryptanalysis for each app that supports encryption (Section 4.2.3)
- Step 3 - Review Android Auto Backup (AAB) usage for each app (Section 5.4)
This step allows you to verify and reproduce:
- Table 1
- Backup Mechanisms (except for Android Backup)
- Table 2:
- PII to use cloud backups
- Backup Location
- TOTP Data Leaked
- Obtain Backup With...
- Table 3
- Password Min Len
For each app, record the network traffic while executing the steps enumerated in
the app checklist (apps/<id@version>/logs/checklist.md
).
The entries in Table 2 can be verified by reviewing the network traffic
snippets that we collected during our research
(apps/<id@version>/logs/traffic-snippet.txt
). These same Table 2 entries can
be reproduced by analyzing your own network traffic recorded while executing
the steps in the checklist for each app.
This step allows you to verify and reproduce:
- Table 3
- Key Source
- KDF and Configuration
- KDF Salt
- Encryption Algorithm
- Ciphertext Integrity
- Decryption Heuristic
For each app that supported encryption, we implemented the decryption process in a separate script to verify our observations. Each script has a section near the top that defines constant variables, including:
- the ciphertext and IV from the network traffic
- if applicable, the password that used when enabling the backup mechanism
- if applicable, any salt passed to a KDF
These scripts are available in the apps/<id@version>/verify_crypto
directory
and require Go 1.18 or higher. To run each script:
$> go mod tidy
$> go run verify_crypto.go
This step allows you to verify the Table 3 fields listed above.
By default, the values for these constants are the actual values that we
observed in real network traffic generated by each app during our research
(apps/<id@version>/logs/traffic-snippet.txt
). Executing the script will verify
the Table 3 findings listed above.
This step allows you to reproduce the Table 3 fields listed above.
To reproduce our cryptanalysis findings, you will need to update the relevant
constants in each script with the values present in your network traffic
captures and/or file exports. Each script is well commented to indicate where
the value can be found in the network traffic generated by the app or exported
file/share created by the app. We also include the relevant network traffic
snippets that we collected from our own network traffic captures during our
research (apps/<id@version>/logs/traffic-snippet.md
) to assist finding the
correct requests/responses and field values in your traffic captures.
To observe that the KDF Salt
used by an app is not static, you can record
network traffic while repeating the app's checklist in the previous step; a new
salt value will be used each time. To fully verify that the KDF Salt is using an
appropriate source of randomness requires reviewing the decompiled app code. We
encourage researchers to do this, but explaining that level of detail for each
app is out of the scope of these instructions.
This step allows you to verify and reproduce:
- Table 1
- Android Backup
Android apps are opted into Android Auto Backup
(AAB) by default,
but developers can explicitly opt-out by setting android:allowBackup="false"
in the app's manifest file. To verify this setting, you can install and use
apktool to view the app's
AndroidManifest.xml
file:
$> java -jar apktool.jar decode something.apk --output apktool_out
$> cd apktool_out
$> cat AndroidManifest.xml | grep allowBackup
The attribute android:allowBackup="false"
means that the app does not
allow data to be backed up via the AAB system. These apps show a -
in Table 1.
Note: Google Authenticator does use Android Auto Backup for some
non-secret fields, but does not backup any TOTP data via AAB.
Therefore, it is marked as -
in Table 1. See paper for details.
Any value other than false
means that the app does allow data to be backed
up via AAB. For these apps, it is necessary to confirm whether TOTP data is,
in fact, backed up by AAB.
Note: We could not get AAB to run without error on the following apps: Aegis Authenticator, andOTP, and FreeOTP Authenticator. See paper for details.
- Ensure that a Google account is registered on the Android device
- If backups are enabled, disable them to erase all backup data
(docs)
- Device Settings >
Google
>Backup
> toggle offBackup by Google One
> clickTurn off & delete
- Device Settings >
- Re-enable automatic backups on your Android device
(docs)
- Device Settings >
Google
>Backup
> turn onBackup by Google One
- Device Settings >
- Install the correct version of the APK on the Android phone
$> adb install-multiple *.apk
- The checklist for each app contains a link to download the correct version of the APK file
- Scan QR Code 1 and do not create any backups within the app
- Uninstall the app
- Verify that no data was backed up via the Android Auto Backup system
- Device Settings >
Google
>Backup
> verifyBackup by Google One
is toggled on and the messageNo data backed up
is displayed
- Device Settings >
- Reinstall the app
$> adb install-multiple *.apk
- Open the app and confirm that no data was backed up
- Scan QR Code 1 again
- Use
adb
to manually trigger an Android Auto Backup for the given app
$> adb shell bmgr backupnow <apk_id>
- Example:
$> adb shell bmgr backupnow com.authenticator.authservice2
- Confirm the backup ran successfully
- The output should include
Package <apk_id> with result: Success
- Example:
Package com.authenticator.authservice2 with result: Success
- If you encounter an error when triggering AAB for an app, try restarting
the phone and repeating the previous step to trigger the backup again.
- Example error:
Transport rejected package because it wasn't able to process it at the time
- Example error:
- Uninstall / reinstall the app
$> adb install-multiple *.apk
- Android should automatically restore the app data when the app is
reinstalled. If it does not, you may need to manually trigger a recovery
for the app:
$> adb shell bmgr restore <apk_id>
- Example:
$> adb shell bmgr restore com.authenticator.authservice2
- Open the app to verify that the backed up data was restored