L2ContractMigrationFacet
contract is vulnerable to signature replay attacks due to the lack of nonce in its signature verification process. This vulnerability allows a malicious user to reuse a valid signature multiple times, potentially leading to unauthorized actions.
Take a look at the verifySignature
function. It uses ECDSA for signature verification but does not implement any mechanism to prevent signature reuse.
The function checks the deadline
but doesn't use a nonce
or mark the signature as used after verification. This allows the same signature to be reused in multiple transactions as long as the deadline hasn't passed.
If not fixed, this signature replay ability will lead to unauthorized and repeated execution of the redeemDepositsAndInternalBalances
function. This can result in:
Duplicate redemption of deposits and internal balances.
Incorrect allocation of assets to the receiver address.
Manipulation of account stalk and roots balances.
Take a look at the redeemDepositsAndInternalBalances
function:
Consider a scenario where:
Alice, a contract owner, signs a valid message to redeem deposits and internal balances to Bob's address.
The transaction is executed successfully using Alice's signature, transferring assets to Bob and updating stalk balances.
An attacker observes this transaction and its signature.
The attacker replays the same transaction with the same signature before the deadline expires.
The contract processes the replayed transaction as valid, leading to:
Duplicate calls to addMigratedDepositsToAccount
, potentially double-crediting deposits to Bob's account:
Repeated execution of setStalk
, incorrectly increasing Bob's stalk and roots balances:
This bug could be exploited multiple times, leading to inflated balances for the receiver (Bob in this case).
The impact is further exacerbated by the fact that the redeemDepositsAndInternalBalances
function is marked as payable
and uses nonReentrant
, suggesting it handles valuable assets and state changes as seen here:
Manual code review
Consider adding a nonce to the signature data structure. Include the nonce in the signed message. Then verify and increment the nonce during signature verification. Additionally, consider exposing a function that marks the current nonce as used, providing a means for the user to revoke signatures.
Another way to fix this is by using OpenZeppelin library for signature verification.
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.