odos signature can be used for other withdraws to make bad swap on odos for protocol
*issue-contents*
0 CONTENTS
- 1................................................................................
- 2................................................................................
- 3................................................................................
- 4................................................................................
- 5................................................................................
- 6................................................................................
- 7................................................................................
- 8................................................................................
- 9................................................................................
1 METADATA
Number | 39 |
---|---|
Severity | High |
Author | volodya |
Contest | Autonomint |
Platform | Sherlock |
2 SUMMARY
There is no invalidation that this signature already used in protocol
3 ROOT CAUSE
In withdraw function signature and odos data passed to cds contract
function withDraw(
address toAddress,
uint64 index,
bytes memory odosAssembledData,
bytes memory signature
) external payable nonReentrant whenNotPaused(IMultiSign.Functions(1)) {
// check is _toAddress in not a zero address and isContract address
if (toAddress == address(0) || isContract(toAddress)) revert Borrow_CantBeContractOrZeroAddress(toAddress);
--> if (!cds.verify(odosAssembledData, signature)) revert Borrow_NotSignedByEIP712Signer();
// Get the depositor details
Blockchian/contracts/Core_logic/borrowing.sol#L290
where signature is not being invalidated anywhere which allows to use it again for any other withdraw for that user
function verify(
bytes memory odosExecutionData,
bytes memory signature
) external view onlyBorrowingContract returns (bool) {
return
_verify(
FunctionName.BORROW_WITHDRAW,
0,
0,
odosExecutionData,
signature
);
}
function _verify(
FunctionName functionName,
uint256 excessProfitCumulativeValue,
uint256 nonce,
bytes memory odosExecutionData,
bytes memory signature
) private view returns (bool) {
bytes32 digest;
...
} else if (functionName == FunctionName.BORROW_WITHDRAW) {
digest = _hashTypedDataV4(
keccak256(
abi.encode(
keccak256("OdosPermit(bytes odosExecutionData)"),
odosExecutionData
)
)
);
}
address signer = ECDSA.recover(digest, signature);
bytes32 hashedSigner = keccak256(abi.encodePacked(signer));
if (hashedSigner == hashedAdminTwo) {
return true;
} else {
return false;
}
}
E.x. there are two positions. E.x.there is upside - 1 wrsETH after first withdraw and 2 wrsEth after second withdraw. Target for odos swap is TREASURY from tests. Everything goes normal user uses 1 signature for first withdrawal - 1 wrsETH exchange for 1000 udst to treasury Everything goes normal user uses second signature for second withdrawal - 2 wrsETH exchange for 2000 udst to treasury
Attacker uses first signature for second withdrawal 1 wrsETH exchange for 1000
udst, but upside left - 2 wrsETH - 1 wrsETH=1wrsETH
left unaccounting. Which
means some holders will not receive their stake which leads to depeging as the
point of protocol to catch upside and distribute correctly
4 INTERNAL PRE-CONDITIONS
none
5 EXTERNAL PRE-CONDITIONS
none
6 ATTACK PATH
use odos data from first withdrawal and use it on another withdrawal.
7 IMPACT
holders will not receive their stake which leads to depeging as the point of protocol to catch upside and distribute correctly
8 POC
9 MITIGATION
Add nonce to invalidate that signature that already used
LINKS
*issue-links*
- 1.