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

Ownership can be transferred to a contract due to evm limitations which then can be used to bypass signatures.

Summary

The transferOwnership allows ownership to be transferred to a contract address, this is because transfer can be called from the constructor of a contract and constructors don't have byte codes.

This creates an issue where a malicious contract can assume ownership and manipulate the signature validation process by always returning true when validating signatures. This could lead to unauthorized operations being validated as legitimate.

Vulnerability Details

The issue stems from calling isValidSignatureNow in the owneraddress and not the signatureCheckerLib

function transferOwnership(address newOwner) external {
require(newOwner != address(0), ZeroAddressNotAllowed());i
require(!\_isContract(newOwner), NewOwnerIsContract());
smartAccountOwners\[msg.sender] = newOwner;
}
function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external view returns (uint256) {
address owner = smartAccountOwners\[userOp.sender];
if (
owner.isValidSignatureNow(ECDSA.toEthSignedMessageHash(userOpHash), userOp.signature) ||
owner.isValidSignatureNow(userOpHash, userOp.signature)
) {
return VALIDATION\_SUCCESS;
}
return VALIDATION\_FAILED;
}

Since anyone can transferOwnershipto themselves they can implement isValidSignatureNowto always return true/false ×

- The transferOwnershipfunction allows any user to transfer ownership of a validator to themselves.

- The function includes a check to ensure that the new owner is not a contract using _isContract(newOwner). Which is bypassed by calling from the constructor.

The validateUserOpfunction calls isValidSignatureNowon the owneraddress to validate the user's signature. Which is manipuliated to always return true.

- Bypassing isContract Check: The _isContractcheck can be bypassed if the ownership transfer is initiated from a constructor, allowing a contract to be set as the new owner.

- Malicious Contract: A malicious contract set as the owner can implement the isValidSignatureNow function to always return true, effectively bypassing the signature validation proces

Impact

The malicious contract can validate any operation by always returning true in the isValidSignatureNow function, leading to unauthorized operations being executed.

Tools Used

Manual Review

Recommendations

Since all address are meant to be EOAs utilize the `SignatureChecker` library for validating signatures to ensure consistent and secure verification. And not the `owner address

function validateUserOp(PackedUserOperation calldata userOp, bytes32 userOpHash) external view returns (uint256) {
address owner = smartAccountOwners\[userOp.sender];
// Use the SignatureChecker library to validate the signature
if (
SignatureChecker.isValidSignatureNow(owner, ECDSA.toEthSignedMessageHash(userOpHash), userOp.signature) ||
SignatureChecker.isValidSignatureNow(owner, userOpHash, userOp.signature)
) {
return VALIDATION\_SUCCESS;
}
return VALIDATION\_FAILED;
}
Updates

Lead Judging Commences

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

finding-isContract-check

Invalid [known issue [Medium-3]](https://github.com/Cyfrin/2024-07-biconomy/issues/1)

Support

FAQs

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