Open TheDZhon opened 1 year ago
Is it allowed to publicly speak about this issue? I would like to take a post about this with a deep dive, which might help other lsd protocols and auditors.
Is it allowed to publicly speak about this issue? I would like to take a post about this with a deep dive, which might help other lsd protocols and auditors.
Hello, @grGred
Since this is a public repo, please feel free to make any further references.
The article suggest another approach for mitigating the attack: https://www.trust-security.xyz/post/permission-denied It might be more coherent to use as a long-term solution.
https://github.com/trust1995/trustlessPermit/tree/main
function trustlessPermit(
address token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
// Try permit() before allowance check to advance nonce if possible
try IERC20Permit(token).permit(owner, spender, value, deadline, v, r, s) {
return;
} catch {
// Permit potentially got frontran. Continue anyways if allowance is sufficient.
if (IERC20(token).allowance(owner, spender) >= value) {
return;
}
}
revert("Permit failure");
}
Summary
Potential griefing vector of withdrawal requests having a pre-signed approval ('permit') signature attached (e.g., no profit motive for an attacker but spoils UX for users of the protocol) by front-running the 'token.permit' calls with intercepted from mempool signatures.
Affected methods
The WithdrawalQueue contract is affected with the following withdrawal request methods:
requestWithdrawalsWstETHWithPermit
requestWithdrawalsWithPermit
These functions are designed to streamline transactions by combining token approval and withdrawal request operations into a single call.
Expected behavior
The
requestWithdrawalsWstETHWithPermit
andrequestWithdrawalsWithPermit
functions utilize the permit function so that approve and pull operations can happen in a single transaction instead of two consecutive transactions.Griefing exploitation
ERC20Permit (
stETH
andwstETH
inherit from this) uses the nonces mapping for replay protection. Once a signature is verified and approved, the nonce increases, invalidating the same signature being replayed. TherequestWithdrawalsWstETHWithPermit
andrequestWithdrawalsWithPermit
functions expect the user to sign their tokens with theWithdrawlQueue
contract address asspender
and submit the transaction to the chain with the signatureuint8 v, bytes32 r, bytes32 s
as part of the arguments. When the user transaction is in the mempool, an attacker can take this signature, call thetoken.permit
function on the token themselves with the following argumentsSince this is a valid signature, the token accepts it and increases the nonce. This makes the user's transaction fail whenever it gets mined.
Potential impact
It's possible to induce
requestWithdrawalsWstETHWithPermit
andrequestWithdrawalsWithPermit
functions reverts via concurrent 3rd-party actions worsening UX.Short-term mitigation
requestWithdrawals
method relying on the already provided allowance seamlessly.Proposed long-term solution
Change the
WithdrawalQueue
implementation to be aware of the existing allowance at execution.This solution will be evaluated for integration in the next protocol update, targeted for Q2/Q3 2024 (tentatively).
This issue was reported responsibly through Immunefi and has been assigned a 'MEDIUM' severity rating under the stipulations of the Lido Bug Bounty Program. The individual initially identified the issue has received a reward concurrent with this publication.