puddly / android-otp-extractor

Extracts OTP tokens from rooted Android devices
GNU General Public License v3.0
238 stars 22 forks source link

Microsoft Authenticator import wrong #33

Closed SuperSandro2000 closed 4 years ago

SuperSandro2000 commented 4 years ago

The TOTP for the Microsoft Account in the Microsoft Authenticator app is 8 numbers long. The code the tool generates tells andOTP to only generate 6 tokens which is not accepted at Microsofts end.

Simply changing to 8 digits does not work either.

puddly commented 4 years ago

I just tried scanning an 8 digit code into Microsoft Authenticator and the digits portion of the otpauth:// URI seems to be ignored. There doesn't seem to be a way to manually add a code and specify the number of digits either.

You can dump your database by running this script? You should be able to see what the format is:

#!/usr/bin/env python3
import pprint
import sqlite3

from android_otp_extractor.adb import guess_adb_interface
from android_otp_extractor.contrib import open_remote_sqlite_database

adb = guess_adb_interface('/data/data/')

with open_remote_sqlite_database(adb, '/data/data/com.azure.authenticator/databases/PhoneFactor') as connection:
    connection.row_factory = sqlite3.Row

    cursor = connection.cursor()
    cursor.execute('SELECT * FROM accounts;')

    for result in cursor.fetchall():
        pprint.pprint(dict(result))
        print()

For comparison, here is what I see with a non-Microsoft account:

{'_id': 1,
 'aad_authority': '',
 'aad_ngc_totp_enabled': 0,
 'aad_permission': 0,
 'aad_tenant_id': '',
 'aad_user_id': '',
 'account_capability': 1,
 'account_type': 0,
 'cached_pin': '',
 'cid': '',
 'encrypted_oath_secret_key': '',
 'group_key': '00000000000000000000000000000000',
 'identity_provider': '',
 'is_totp_code_shown': 1,
 'mfa_pin_encryption_key_alias': '',
 'name': 'uihiuh',
 'ngc_ski': '',
 'oath_enabled': 0,
 'oath_secret_key': '6tfrwfx2ignyo74d4tnsqbtdxbbgjekn4leewvojw4gnfivaoakqx4kr',
 'paws_url': '',
 'restore_capability': 0,
 'update_flags': 0,
 'username': 'uihiuh',
 'ux_position': 0}
SuperSandro2000 commented 4 years ago

I get the following (replaced secret values):

{'_id': 1,
 'aad_authority': '',
 'aad_ngc_totp_enabled': 0,
 'aad_permission': 0,
 'aad_tenant_id': '',
 'aad_user_id': '',
 'account_capability': 7,
 'account_type': 1,
 'cached_pin': '',
 'cid': '1234567890abcdef',
 'encrypted_oath_secret_key': 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=',
 'group_key': '00000000000000000000000000000000',
 'identity_provider': '',
 'is_totp_code_shown': 1,
 'mfa_pin_encryption_key_alias': '',
 'name': 'Microsoft',
 'ngc_ski': 'jk6_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-48',
 'oath_enabled': 1,
 'oath_secret_key': 'xxxxxxxxxxxxxx==',
 'paws_url': '',
 'restore_capability': 0,
 'username': 'my.mail@mail.mail',
 'ux_position': 0}

I tested 8 digist with andOTP and it showed me 8 digits but this also did not work. Notable differences in the output are cid, encrypted_oath_secret_key and ngc_ski.

Those values are not worked with in https://github.com/puddly/android-otp-extractor/blob/master/src/android_otp_extractor/apps.py#L140 but I am not sure how to add this without breaking the normal TOTP functionality.

puddly commented 4 years ago

I don't handle encrypted_oath_secret_key at all. I'll check out how the app uses it.

SuperSandro2000 commented 4 years ago

Thanks for looking into that. If you need some more information, testing or anything else I could help with feel free to ping me.

puddly commented 4 years ago

Authenticator uses the Android KeyStore which means it's not possible to decrypt the secret easily.

However, with root access it should be possible to just pretend to be the app and interface with the KeyStore to decrypt the data (since we're not actually interested in the cryptographic material handled by the TPU, just the decrypted key, as intended).

I believe the only thing required is a simple KeyStore Java "proxy" that can be run with su as the appropriate app user. I don't have much experience with Java but I'll give it a go.

puddly commented 4 years ago

I've got a prototype working that can decrypt the andOTP database using this method but it requires setenforce 0 and does IPC in a strange way. Once I get the code cleaned up and tighten up security, android-otp-extractor should be able to export secrets from any app.

puddly commented 4 years ago

@SuperSandro2000 I may be over complicating this. Can you run that script again and take the oath_secret_key and fix its encoding with this code?

>>> import base64
>>> base64.b32encode(base64.b64decode('8UzXgg9agj7MNq=='))
b'6FGNPAQPLKBD5TBW'

See if your secret will work then with 8 digits and a 30 second period. I can't get Microsoft Authenticator running on my primary phone but this works on a much older Android phone.

SuperSandro2000 commented 4 years ago

Yeah that works. :)