Merkle-tree leaves, which are single-hashed are vulnerable to second preimage attacks.
The vulnerable code is in L2ContractMigrationFacet::verifyDepositsAndInternalBalances
function, which generates a leaf and then verifies it with the merkle root, this function is called in a redeem function, which helps with unlocking deposits and bean-tokens on L2 networks:
Generally second preimage attack in Merkle-trees is called when an intermediate node is presented as a leaf. More specifically if an attacker can present a "leaf" that the contract successfully verifies, but that "leaf" will not be the one in the original Merkle-tree.
I'm providing a link with additional explanation of the attack path here: https://crypto.stackexchange.com/questions/81981/how-does-second-pre-image-attack-on-merkle-signature-scheme-work
An example, consider the following merkle-tree:
Suppose a user must create a proof for leaf 1 (h1)
, so the proof must be h0, h23, h4567
, since the higher based hashes are concatenating with the child values.
Attack scenario:
Based on how hash proofs are generated, if an attacker provides h23
and h4567
as a proof, the contract will consider h01
as the leaf, which is result of h(h0 + h1)
.
So if the proof is h23, h4567
it will be accepted as a valid one. Thus, a shortened version will also be accepted, if the first value is passed in the original proof (user's proof) as a leaf.
An attacker will succeed to generate like a "fake-valid" leaf, and a proof which will be valid for the contract.
Attacker can steal bean-funds, this way.
Impact: High, theft of funds from honest users is involved
Likelihood: High, as an attacker will be incentivized to execute the attack
Manual Review
As OpenZeppelin suggests, double hash the leaf:
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.