The bridge.cairo
contract implements a cross-chain token bridge between L1 and L2. One of its key functions, withdraw_auto_from_l1()
, is responsible for processing withdrawal requests originating from L1. This function is crucial for maintaining the integrity and security of the bridge, as it handles the transfer or minting of tokens on L2 based on the information provided in the withdrawal request.
The withdraw_auto_from_l1()
function takes two parameters: from_address
(the L1 sender address) and req
(the withdrawal request details). It first checks if the bridge is enabled and verifies that the from_address
matches the stored bridge_l1_address
. However, a critical security check is missing: the function does not verify the integrity of the req
data by recomputing and comparing its hash.
The Request
struct contains essential information such as token IDs, owner addresses, and URIs. Without proper hash verification, an attacker could potentially alter this data after it has been signed on L1 but before it reaches L2, leading to unauthorized withdrawals or minting of tokens.
This issue stems from an incomplete implementation, as evidenced by the TODO comment in the code:
The absence of these crucial checks opens up a significant security hole in the bridge's withdrawal process.
Relevant code:
An attacker could alter the request data and withdraw tokens they do not own, leading to significant financial losses for users of the bridge.
Alice initiates a legitimate withdrawal request on L1 to withdraw 10 tokens of ID 1234 to her address 0xAlice on L2.
The L1 contract signs this request and sends it to L2.
An attacker intercepts this request before it reaches the L2 withdraw_auto_from_l1()
function.
The attacker modifies the req
data, changing the owner_l2
to their address 0xAttacker and potentially altering the token_id
or quantity.
The attacker submits this modified request to the withdraw_auto_from_l1()
function.
The function processes the request without verifying the hash, resulting in the tokens being minted or transferred to the attacker's address instead of Alice's.
Manual review
To mitigate this issue, implement hash verification for the req
data in the withdraw_auto_from_l1()
function. This will ensure that the request data has not been tampered with after being signed on L1.
Here's a diff of the recommended changes:
You guys can also implement comprehensive validation for all fields in the req
struct to ensure they conform to expected values and ranges. This may include checks for valid addresses, token IDs, and other relevant data.
Please, do not suppose impacts, think about the real impact of the bug and check the CodeHawks documentation to confirm: https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity A PoC always helps to understand the real impact possible.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.