Entrust IdentityGuard Enrollment

If you would like to follow along, you can sign up for an IntelliTrust trial, which will allow you to enroll IdentityGuard soft tokens, at https://entrust.us.trustedauth.com/#/signup

To begin analyzing the Entrust enrollment process, we’ll need a QR code. Thankfully, searching Google Images for something like “entrust identityguard qr code” gives us useful results like https://www.umc.edu/DIS/files/Entrust%20Files/ios-soft-token-via-qr-code-entrust-identityguard-registration-tip-sheet.pdf.

Once we extract the QR code from that PDF and decode it, we see the following data:

igmobileotp://?action=secactivate&enc=VRUq6IoLWQRCMRITZEHtHUSWJiPwgu%2FN1BFyUHE5kxuHIEYoE3zmNTrAHeeUM5S3gzCnTy%2F%2Bdnbu%2FsjjQW%2BNEISx8C4ra8rLpxOl8E8w4KXHgjeBRgdvSzl%2BbzX5RYRrQlWgK8hsBT4pQYE0eFgW2TmRbzXu1Mu7XjKDcwsJLew32jQC2qyPLP8hljnv2rHwwsMfhQwgJUJYfctwLWWEDUFukEckaZ4O&v=1&mac=mhVL8BWKaishMa5%2B

Immediately we can see this is drastically different from the process we dealt with for standard TOTP tokens. Of note is the different URL handler, which indicates this QR code is only able to be used with the IdentityGuard application, and the enc and mac parameters, indicating the data contained within is encrypted somehow. This is confirmed by viewing the enrollment PDF again, which contains a password next to the QR code.

To aid in further investigation, I’m going to switch to using an example enrollment email from the IntelliTrust trial, which allows me to choose which activation methods can be used for the token. By default, all methods are selected, which results in an email looking like this:

This email indicates there are three ways to enroll a token: online enrollment using a URL, offline enrollment using a QR code, or offline enrollment using an address, serial, and activation code.

From here we’re going to need to use some reverse engineering and brute-force to determine how the enrollment takes place. I won’t go into the details of how I performed this here, but the result of this work can be found on my GitHub: https://github.com/ss23/entrust-identityguard-tools/

Entrust IdentityGuard QR Codes

The QR code data contains a salt/nonce, which when combined with the password using PBKDF2-HMAC-SHA256, generates an AES key to decrypt the data:

ss23@crisp $ ./decode-qr-uri.py 'igmobileotp://?action=secactivate&enc=UuMXVIqUa8RglsnNYY7eUb9hHJX7WZMO0dq95remibffJhkjhmOYjNezwh2%2Bx7pEqy4tNPIfsqg2Hzwx0a78fbeox0i6crZY0dO4PQfe3XUSBx%2B8cw79TmgKybUo2kfX385sSif8v5rP46uaaXk3jV3xrarfjDNRU7%2FJ0YZ64v65GMlOzoFI5Kz64vnKFwdY9xqCsBF110Q%3D&v=1&mac=9mRPt5k%2FBAM56bR2' 76916364 {"sn":"18924-27533","ac":"0186-3302-4398-6152","policy":"{\"allowUnsecured\":\"false\"}","regurl":"ss23.us.trustedauth.com/api/mobile"}

This shows us the first vulnerability in this kind of design. The password used to decrypt the QR code is far too short and simple to be robust against a brute-force attack. To search the entire keyspace using only CPUs can be done with a few dollars on Amazon AWS (see the README on https://github.com/ss23/entrust-identityguard-tools), and can surely be optimized even further with a GPU implementation. There’s an argument to be made that because the decrypted data only contains information that is present in the previous email, it doesn’t result in less security if it can be decrypted, but the fundamental flaw is that people working with these QR codes assume them to not be bruteforcable. This means people are happy to send the QR codes through email (even Entrust themselves, through their IntelliTrust platform, send these codes via email), or transmit them through other insecure means, with the assumption that they’re protected and don’t present a meaningful security risk alone.

Entrust IdentityGuard Registration

At this stage we don’t yet have the underlying TOTP secret, so we need to understand how the Entrust application uses the information we do have. An easy way to verify what is taking place is by scanning the same QR code (or entering the information decoded from it) twice. If the generated codes are the same on both devices, we know the information within the QR code is all that is used to generate the TOTP token. If it’s different, there must be more taking place.

The Entrust application generates unique tokens every time we scan the same QR code, which indicates there must be some kind of other process going on that results in the underlying secret being generated and communicated back to the server. This makes sense, as part of the enrollment process involves submitting a “Registration Code” (not to be confused with an Activation Code) back to the enrollment server. This must mean that whatever the secret is, the server can determine it based on the Registration Code. Luckily, we can once again look at the applications code, and with some reverse engineering, determine what is going on.

Using the information in the QR code, the application generates a “secret” of 2 bytes on the device. This is then combined with the other information and merged into the Registration Code. When the server receives the Registration Code, it can link it back to a specific enrollment, and determine the underlying OTP secret.

To verify this, we can use an example we’ve previously added to the device. If we can generate the same tokens as the application does, we’ll know we’ve obtained the true OTP secret:

ss23@crisp $ ./generate-otp.py 18924-27533 0186-3302-4398-6152 24211-55785

35695cd4c2c90fe30c5cf04f1ccd48ea

To generate a code immediately, run:

oathtool -v --totp=sha256 --digits=6 35695cd4c2c90fe30c5cf04f1ccd48ea ss23@crisp $ oathtool -v --totp=sha256 --digits=8 35695cd4c2c90fe30c5cf04f1ccd48ea

Hex secret: 35695cd4c2c90fe30c5cf04f1ccd48ea

Base32 secret: GVUVZVGCZEH6GDC46BHRZTKI5I======

Digits: 8

Window size: 0

Step size (seconds): 30

Start time: 1970-01-01 00:00:00 UTC (0)

Current time: 2019-10-24 10:13:12 UTC (1571911992)

Counter: 0x31F840A (52397066) 52112886

This confirms that everything we need to determine the secret is contained within the QR code and Registration Code. Once again, this presents a massive security risk to the solution depending on how it is deployed. There is a natural inclination in a lot of circumstances to simply respond to the person enrolling your token with the Registration Code that was generated. If this is communicated over a persistent channel such as email, an attacker may be able to obtain all the information required to generate a token without anyone knowing. As before, this is not an overt security flaw, but rather a problem with the human parts of the system. If someone is not aware that the QR code and Registration Code contain all that is required to generate new tokens, they’ll not be inclined to protect them. Simply by obfuscating the process of generating these codes, Entrust has substantially decreased how secure their product is in practice.

Entrust IdentityGuard Entropy

Within the previous section, there was another flaw briefly mentioned: only two random bytes are generated on the end-users’ device. As with all the other discussed flaws, this is not an overt security issue, but one of subverting the users’ expectations. After hearing that the Registration Code and QR code contain enough to generate future TOTP outputs, a first reaction is to prevent both of these pieces of information from being found in the same place. In practice, this often means emailing the QR code (as this is an image, and thus hard to communicate through other channels), and sending the Registration Code component through a second channel, such as voice or SMS. This is still a severely flawed practice due to the limited entropy being generated on the end-users’ device.

By observing the QR code, along with a single output of the TOTP token, it is possible to find the correct seed through a brute-force attack. This goes back to the initial problem with TOTP mentioned in the introduction: TOTP is phishable. If an attacker can phish a single output of the token, the attack becomes possible. Something like this becomes even more plausible if you are willing to call an end-user and ask for an “Entrust verification code” or similar without asking for their password. Most users are willing to give out MFA codes over the phone, especially if you emphasize you are not asking for their password.

Putting this into practice with a specific example (with the same values as used previously):

ss23@crisp $ ./crack-otp.py 18924-27533 0186-3302-4398-6152 52112886 1571911992 Possibe valid OTP seed found: 35695cd4c2c90fe30c5cf04f1ccd48ea

To generate a code immediately, run:

oathtool -v --totp=sha256 --digits=6 35695cd4c2c90fe30c5cf04f1ccd48ea

This is the same secret code as we had before, confirming we can now generate new codes the same as the device into the future.