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

Owner Replacement in K1Validator.sol

Summary

The K1Validator contract allows for the transfer of ownership using the transferOwnership function. However, this function does not implement sufficient security measures to prevent unauthorized ownership changes. This vulnerability can be exploited by attackers to gain control over the smart accounts associated with legitimate owners.

Vulnerability Details

The transferOwnership function allows changing the owner of a smart account without any restrictions. This could potentially lead to unauthorized ownership changes if the caller is compromised.

function transferOwnership(address newOwner) external {
require(newOwner != address(0), ZeroAddressNotAllowed());
require(!_isContract(newOwner), NewOwnerIsContract());
smartAccountOwners[msg.sender] = newOwner;
}

Impact

  • If the transferOwnership function is exploited, an attacker could replace the legitimate owner with their own address. This would give the attacker complete control over the smart account associated with the original owner. For example an attacker gains access to the smart account's private key and calls transferOwnership to set themselves as the new owner. They can then perform any operations that require owner authorization, including transferring funds, modifying contract state, or executing arbitrary transactions.

  • The attacker can drain funds from the smart account by executing transactions that transfer assets to addresses they control. This could result in a total loss of the smart account's assets.

  • By repeatedly changing the owner, an attacker could prevent the legitimate owner from regaining control or accessing the smart account. This would effectively lock the legitimate owner out of their account.

  • If users lose control of their smart accounts due to this vulnerability, it can damage the reputation of the platform deploying the contract. Users might lose trust in the security and reliability of the system.

Tools Used
Manual Review

Recommendations

  • Introduce a two-step process for transferring ownership, requiring confirmation from both the current and new owner.

mapping(address => address) private pendingOwners;
function initiateOwnershipTransfer(address newOwner) external {
require(newOwner != address(0), ZeroAddressNotAllowed());
require(!_isContract(newOwner), NewOwnerIsContract());
pendingOwners[msg.sender] = newOwner;
}
function confirmOwnershipTransfer() external {
address newOwner = pendingOwners[msg.sender];
require(newOwner != address(0), "No pending owner");
smartAccountOwners[msg.sender] = newOwner;
delete pendingOwners[msg.sender];
}
  • Introduce a time-delay mechanism where the ownership change only takes effect after a certain period. This gives the current owner time to react if an unauthorized transfer is initiated.

    struct PendingTransfer {
    address newOwner;
    uint256 effectiveTime;
    }
    mapping(address => PendingTransfer) private pendingTransfers;
    uint256 constant TRANSFER_DELAY = 1 days;
    function initiateOwnershipTransfer(address newOwner) external {
    require(newOwner != address(0), ZeroAddressNotAllowed());
    require(!_isContract(newOwner), NewOwnerIsContract());
    pendingTransfers[msg.sender] = PendingTransfer(newOwner, block.timestamp + TRANSFER_DELAY);
    }
    function confirmOwnershipTransfer() external {
    PendingTransfer memory pending = pendingTransfers[msg.sender];
    require(pending.newOwner == msg.sender, "Not pending owner");
    require(block.timestamp >= pending.effectiveTime, "Transfer not yet effective");
    smartAccountOwners[msg.sender] = pending.newOwner;
    delete pendingTransfers[msg.sender];
    }


    - Require multiple signatures (multisig) for sensitive operations like ownership transfer. This adds an additional layer of security by requiring consensus among multiple parties.

    mapping(address => mapping(address => bool)) private approvals;
    uint256 constant MIN_APPROVALS = 2;
    function approveTransfer(address newOwner) external {
    approvals[msg.sender][newOwner] = true;
    }
    function confirmOwnershipTransfer(address newOwner) external {
    uint256 approvalCount = 0;
    for (uint256 i = 0; i < owners.length; i++) {
    if (approvals[owners[i]][newOwner]) {
    approvalCount++;
    }
    }
    require(approvalCount >= MIN_APPROVALS, "Not enough approvals");
    smartAccountOwners[msg.sender] = newOwner;
    }
Updates

Lead Judging Commences

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

finding-K1Validator-access-control-issues

- Transfer of ownerships/uninstallation/installation of modules is gated to the caller, wherein the new owner can only adjust the `smartAccountOwners` storing the current owner based on caller (`msg.sender`) that called the `transferOwnership()` function. This functionalities should - Known issue > A Nexus Smart Account could be locked forever if the owner installs a validator in the wrong way and does remove all other valid validators

Support

FAQs

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