code-423n4 / 2023-09-maia-findings

25 stars 17 forks source link

if the Virtual Account's owner is a Contract Account (multisig wallet), attackers can gain control of the Virtual Accounts by gaining control of the same owner's address in a different chain #877

Open c4-submissions opened 1 year ago

c4-submissions commented 1 year ago

Lines of code

https://github.com/code-423n4/2023-09-maia/blob/main/src/RootPort.sol#L350-L353

Vulnerability details

Impact

Proof of Concept

BranchBridgeAgent.sol

function callOutSignedAndBridge(
...
) external payable override lock {
...
//Encode Data for cross-chain call.
bytes memory payload = abi.encodePacked(
_hasFallbackToggled ? bytes1(0x85) : bytes1(0x05),
//@audit-info => Encodes the address of the caller in the Branch and sends it to the RootBridgeAgent
//@audit-info => This address will be used to fetch the VirtualAccount assigned to it!
msg.sender,
_depositNonce,
_dParams.hToken,
_dParams.token,
_dParams.amount,
_dParams.deposit,
_params
);
}

RootBridgeAgent.sol


function lzReceiveNonBlocking(
...

) public override requiresEndpoint(_endpoint, _srcChainId, _srcAddress) { ... ... ... else if (_payload[0] == 0x04) { // Parse deposit nonce nonce = uint32(bytes4(_payload[PARAMS_START_SIGNED:PARAMS_TKN_START_SIGNED]));

  //Check if tx has already been executed
  if (executionState[_srcChainId][nonce] != STATUS_READY) {
      revert AlreadyExecutedTransaction();
  }

  //@audit-info => Reads the address of the msg.sender in the BranchBridgeAgent and forwards that address to the RootPort::fetchVirtualAccount()
  // Get User Virtual Account
  VirtualAccount userAccount = IPort(localPortAddress).fetchVirtualAccount(
      address(uint160(bytes20(_payload[PARAMS_START:PARAMS_START_SIGNED])))
  );

  // Toggle Router Virtual Account use for tx execution
  IPort(localPortAddress).toggleVirtualAccountApproved(userAccount, localRouterAddress);

...
...

} ... ... }

> RootPort.sol
```solidity
//@audit-info => Receives from the RootBridgeAgent contract the address of the caller in the BranchBridgeAgent contract
//@audit-info => Fetches the VirtualAccount assigned to the _user address regardless from what Branch the call came from
function fetchVirtualAccount(address _user) external override returns (VirtualAccount account) {
    account = getUserAccount[_user];
    if (address(account) == address(0)) account = addVirtualAccount(_user);
}

Tools Used

Manual Audit & Article wrote by Rekt

Recommended Mitigation Steps

Assessed type

Access Control

c4-pre-sort commented 1 year ago

0xA5DF marked the issue as sufficient quality report

c4-pre-sort commented 1 year ago

0xA5DF marked the issue as primary issue

c4-sponsor commented 1 year ago

0xBugsy (sponsor) disputed

c4-sponsor commented 1 year ago

0xLightt (sponsor) confirmed

0xLightt commented 1 year ago

Contracts should not use Virtual Accounts and deploying a specific router for contract usage is most likely the safest option.

c4-judge commented 1 year ago

alcueca marked the issue as satisfactory

c4-judge commented 1 year ago

alcueca marked the issue as selected for report

alcueca commented 1 year ago

This is related to #351 in the wrong assumption that a given address is controlled by the same individual in all chains. There are different attack vectors and impacts, but fixing that core assumption will solve all of them.

c4-judge commented 1 year ago

alcueca changed the severity to 3 (High Risk)

c4-judge commented 1 year ago

alcueca marked the issue as duplicate of #351

c4-judge commented 1 year ago

alcueca marked the issue as not selected for report

c4-judge commented 1 year ago

alcueca changed the severity to 2 (Med Risk)

c4-judge commented 1 year ago

alcueca marked the issue as selected for report

alcueca commented 1 year ago

Leaving this group as Medium, as this warden estimated it. The underlying issue is assuming that the same addresses are controlled by the same people in different chains, which is not necessarily true. While the sponsor states that contracts should not use virtual accounts, that is not specified in the documentation, and might only have been discovered in a future issue of rekt.

c4-judge commented 1 year ago

alcueca changed the severity to 3 (High Risk)

khalidfsh commented 1 year ago

Greetings all, judge @alcueca

While I appreciate the in-depth analysis presented in the report, there's a fundamental discrepancy when it comes to the exploitability of the vulnerability mentioned.

The report suggests that on Polygon, an attacker could simply gain control of an address identical to the MultiSigWallet from Avax. However, referring to a recent real-world scenario as detailed in the Wintermute incident, we observe that this assumption may be oversimplified.

The Wintermute incident underscores the intricacies and challenges involved in gaining control of a similar address on a different chain:

  1. The address would have to be unclaimed or unused on the target chain.
  2. Assuming the MultiSigWallet is used across multiple chains, the rightful owners might have already claimed the address.
  3. Even if the address is unclaimed, there are intricate steps involving replicating nonce values and other parameters to 'hijack' the address, and this is far from being straightforward.

Given these complexities and the potential for failure, it's crucial to approach the reported vulnerability with a nuanced understanding of its practical exploitability.

Thank you for considering this perspective, and I'd appreciate any further insights on this matter.

JeffCX commented 1 year ago

Agree with the above comments that there maybe some efforts involved to gain control the same address

but the wrong assumption that same address is controlled by same person when using smart contract wallet does cost wintermute lose 20M OP token

so once fund are lost and the lost amount is large

you know in case of wintermute, the multisig wallet is created using the opcode "CREATE" instead of "CREATE2" and the create opcode is not really deprecated, and still be used

cc the original author @stalinMacias

JeffCX commented 1 year ago

more info about the CREATE opcode https://www.evm.codes/#f0?fork=shanghai and deterministic address, https://coinsbench.com/a-comprehensive-guide-to-the-create2-opcode-in-solidity-7c6d40e3f1af

anyway, agree with high severity because the potential lose of fund is large

alcueca commented 1 year ago
image

And then I upgraded it to High immediately after. I have no idea what happened.

Anyway, there is a significant chance of actual losses because of this vulnerability, that don't need to be enabled by any unlikely prior. The severity is High.

0xBugsy commented 1 year ago

Addressed at https://github.com/Maia-DAO/2023-09-maia-remediations/commit/4df0350023d8e49055254c3973d472bcd3f57e33