Broken LAContext canEvaluatePolicy
authorization check
Description
Family Wallet uses a check to LAContext.canEvaluatePolicy(..)
to determine if a user presence check is needed for a given action. The check relies on canEvaluatePolicy(..)
returning true
if a device-authentication mode is configured. This check is used in multiple places in the codebase, namely the LocalProtectedStore
and RemoveWalletFlowViewController
.
A problem with relying on the return value of canEvaluatePolicy(..)
to determine if a device-protection method has been configured on the device is that if that very same device auth method has been timed out via excessive attempts, then canEvaluatePolicy(..)
will begin to return false
. This introduces a bypass to this logic, allowing an attacker to get around this initial prompt to confirm user presence.
Depending on the circumstance, this can have minimal impact. For example, in the LocalProtectedStore
, assuming that a secret was generated and stored in the keychain when the device had an auth method configured, accessing that entry should still require the user to validate the authorization requirements configured on the entry. However, this does not necessarily configure to entries stored in the keychain earlier if they were stored before a device authorization method was configured.
Notably, while LocalProtectedStore
is partially protected via the keychain access control requirements configured on the keychain entries, RemoveWalletFlowViewController
is not so lucky. Using this attack, an attacker is able to get around the control put in place to prevent inadvertant, or malicious wallet removal.
Impact
This flaw in trusting the output of LAContext.canEvaluatePolicy(..)
to determine if authentication is configured on the device can allow access to some secrets, if generated and saved when an authentication method was previously not present. Additionally, it allows an attacker to bypass the user presence requirements when removing a wallet.
Recommendations
Consider checking the returned error value for lockout conditions to determine if an operation should or should not proceed.
Remediation
This issue was remediated in the following commits:
825723d0166e3ba02dd46900e582cbf82019d17b
8e781c122d462efd068aba2d5ff10eca8a6f6c90