Closed code423n4 closed 2 years ago
Mentioned in the readme file :
Some functions of the protocol require admin rights (onlyOwner).
The contracts are owned by the [TimelockController] (https://docs.openzeppelin.com/contracts/4.x/api/governance#TimelockController) contract from OpenZeppelin, set with a >7-days delay. This ensures the community has time to review any changes made to the protocol.
The owner of the TimelockController is a three-party multisignature wallet.
During the next phase of the protocol, the ownership will be transferred to a fully decentralized DAO.
Agree with sponsor - two of the recommendations the warden described to fix this issue are already in place, so this issue is not valid.
Lines of code
https://github.com/code-423n4/2022-02-nested/blob/fe6f9ef7783c3c84798c8ab5fc58085a55cebcfc/contracts/abstracts/MixinOperatorResolver.sol#L86-L103
Vulnerability details
[WP-H0]
Owner
ofZeroExStorage
can drain all the funds from the protocol, and steal tokens from users' walletsThe current design/implementation allows the
Owner
ofZeroExStorage
to execute arbitrary calls to any address by setting a new_swapTarget
onZeroExStorage
, and calling:NestedFactory#create()
->_submitInOrders()
->_submitOrder()
->callOperator()
->_operator.implementation.delegatecall()
->ZeroExOperator#performSwap()
->ExchangeHelpers.fillQuote()
->_swapTarget.call(_swapCallData)
.This can be effectively used as a backdoor/attack vector for a malicious/compromised
Owner
ofZeroExStorage
to steal all the funds not only from the protocol's holdings, but also from users' wallets.https://github.com/code-423n4/2022-02-nested/blob/fe6f9ef7783c3c84798c8ab5fc58085a55cebcfc/contracts/abstracts/MixinOperatorResolver.sol#L86-L103
https://github.com/code-423n4/2022-02-nested/blob/fe6f9ef7783c3c84798c8ab5fc58085a55cebcfc/contracts/operators/ZeroEx/ZeroExOperator.sol#L21-L38
The
require
statements at L36-37 won't effectively prevent the arbitrary code execution, as the attacker can use two FAKE tokens to bypass such restrictions. See appendix:FAKETokens.sol
for details.https://github.com/code-423n4/2022-02-nested/blob/fe6f9ef7783c3c84798c8ab5fc58085a55cebcfc/contracts/libraries/ExchangeHelpers.sol#L14-L23
PoC
Attack Vector A: Steal from users' wallets.
Given:
NestedFactory
to spendWBTC
;100e8 WBTC
in their wallet balance.A malicious/compromised
Owner
ofZeroExStorage
can do the following to steal tokens from users' wallets.ZeroExStorage.sol#updatesSwapTarget()
and set_swapTarget
toWBTC
;NestedFactory.sol#create()
with_originalTokenId
= 0, and_batchedOrders
=As a result, the
100e8 WBTC
belongs to Alice is now stolen by the Hacker.The steps above can be repeated for all tokens and users, effectively stealing all the token balances from all the wallets that approved
NestedFactory
up to the allowance limit, which usually is unlimited.Attack Vector B: Steal funds from the protocol
Given:
1000e8 WBTC
is stored inNestedReserve
.A malicious/compromised
Owner
ofZeroExStorage
can do the following to steal funds fromNestedReserve
.ZeroExStorage.sol#updatesSwapTarget()
and setNestedReserve
toWBTC
;NestedFactory.sol#create()
with_originalTokenId
= 0, and_batchedOrders
=As a result,
1000e8 WBTC
is stolen by the Hacker.The steps above can be repeated for all tokens, effectively stealing all the funds in the protocol.
Recommendation
NestedFactory
to hold users' allowances;callOperator()
to eliminate the possibility of arbitrary calls asFactory
.ZeroExStorage
;updatesSwapTarget()
should be timelocked;Appendix
FAKETokens.sol