Missing selector validation
Description
Social account-recovery happens in two steps. First, a recovery request signed by a sufficient number of guardians is submitted to the account-recovery module. The request is validated and recorded together with the submission timestamp. A second request can then be submitted to execute the recorded recovery request. Execution is only authorized if a security delay has passed.
Therefore, recovery requests are regular UserOperation
s validated by the account-recovery module. The module only allows transactions that call the smart account execute
function to in turn call the account-recovery module itself, with zero ETH value and a selector that corresponds to submitRecoveryRequest
, the function that records the submission of a recovery request.
However, the account-recovery module's validateUserOp
function is not ensuring that the selector for the operation it is validating corresponds to execute
.
Impact
This issue allows guardians to invoke functions other than execute
. We note that this issue allows to bypass the security delay. However, we also note that it can only be exploited by enough malicious and/or compromised guardians that is at least equal to the security threshold set by the smart account owner.
Due to the checks performed by validateUserOp
, the calldata passed to the function has several constraints. However, we were able to write a proof of concept (see the appendix ref↗) where updateImplementation
is invoked, substituting the address of the implementation invoked by the proxy and irrecoverably breaking the smart account.
Recommendations
Ensure the selector of the UserOperation
corresponds to the execute
function.
Remediation
This issue has been acknowledged by Biconomy Labs, and a fix was implemented in commit f9be1c60↗.