HardhatFoundry
30,000 USDC
View results
Submission Details
Severity: low
Invalid

Fallback handlers can trick owners into calling functions of the `Nexus` contract

Summary

Attackers can craft a malicious fallback handler with a clashing function selector to trick smart account owners into calling inbuilt functions.

Vulnerability Details

Nexus smart accounts allows the owner to install fallback handlers which provide extensibility to the account, allowing additional functionality not present in the implementation to be added and called through the fallback function.

ModuleManager.sol#L94-L109

if (calltype == CALLTYPE_SINGLE) {
assembly {
calldatacopy(0, 0, calldatasize())
// The msg.sender address is shifted to the left by 12 bytes to remove the padding
// Then the address without padding is stored right after the calldata
mstore(calldatasize(), shl(96, caller()))
if iszero(call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
returndatacopy(0, 0, returndatasize())
return(0, returndatasize())
}
}

Function dispatch in Solidity is done using function selectors. Selectors are represented by the first 4 bytes of the keccak hash of the function signature (name + argument types). It is possible (and not computationally difficult) to find different functions that have the same selector.

This means that a malicious actor can craft a fallback handler with a function signature carefully selected to match one of the functions present in the Nexus contract, and with an innocent looking implementation. While the fallback implementation may seem harmless, this function when called will actually trigger the function in the Nexus contract.

For example:

  • BaseAccount.withdrawDepositTo() has the function signature of 0x4d44560d

  • Attacker creates a fallback handler with a function which also has a signature of 0x4d44560d. This function looks harmless.

  • Owner of a Nexus account installs the fallback handler using installModule().

  • Owner attempts to call the function in the fallback handler:

    • When his transaction is sent through the entrypoint contract, it ends up calling BaseAccount.withdrawDepositTo() instead as it has the same function signature.

    • ETH is transferred out of the account to the to address.

In this example, through the malicious fallback handler, the attacker tricks the owner into transferring ETH out of his Nexus account.

This is similar to the exploit reported on proxies in this article, which caused the proposal of the transparent proxy pattern.

Impact

Owners of Nexus accounts can be tricked into calling sensitive functions in Nexus implementation, such as withdrawDepositTo().

Recommendations

Consider documenting that modules with clashing function selectors should not be installed or called.

Additionally, consider checking for these selectors in _installFallbackHandler() and reverting if the owner attempts to install them.

Updates

Lead Judging Commences

0xnevi Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-fallback-handler-selector-clash

This is a very clever exploit, however, would be dependent on - The user installing the malicious fallback handler. - Additionally, it is highly contraint because it would require the input parameters (`to` and `amount`) of `withdrawDepositTo()` that is also considered when determining the function signature to coincide with the same input parameters of the malicious functionality of the fallback handler Issues #185 and #190 are pointing to similar function clashing root causes so duplicating, but does lack a similar detailed explanation of exploit path.

Appeal created

0xnevi Lead Judge
10 months ago
0xnevi Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue
Assigned finding tags:

finding-fallback-handler-selector-clash

This is a very clever exploit, however, would be dependent on - The user installing the malicious fallback handler. - Additionally, it is highly contraint because it would require the input parameters (`to` and `amount`) of `withdrawDepositTo()` that is also considered when determining the function signature to coincide with the same input parameters of the malicious functionality of the fallback handler Issues #185 and #190 are pointing to similar function clashing root causes so duplicating, but does lack a similar detailed explanation of exploit path.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.