Submitted by rayn
UniV3LpVault.sol#L621
UniV3LpVault.sol#L379
UniV3LpVault.sol#L520
UniV3LpVault.sol#L521
UniV3LpVault._swap utilizes swapRouter.exactInput to perform swaps between two tokens. During swaps, transfer function of each token along the path will be called to propagate the assets.
Since anyone can create a uniswap pair of arbitrary assets, it is possible to include intermediate hop with malicious tokens within the path. Thus UniV3LpVault._swap effectively grants users the ability to perform arbitrary contract calls during the swap process if swapPath is not validated properly.
Usage of invalidated swapPath can be found in UniV3LpVault.flashFocusCall and UniV3LpVault.repayDebt.
The security of Comptroller and UniV3LpVault relies on validating all used tokens thoroughly. This is done by a whitelist mechanism where admin decides a predefined set of usable tokens, and users can only perform actions within the allowed range. This whitelist approach eliminates most of the attack surface regarding directly passing in malicious tokens as arguments.
Apart from passing malicious tokens directly, there are a few other potential weaknesses, the most obvious one is leveraging flash loans for collaterals. However, due to the adoption of AAVE LendingPool, the external validation within flash loan pool blocks this approach.
Unfortunately, a more obscure path exists. Looking at the swapping mechanism, it is not hard to realize it is backed by uniswapV3. An interesting characteristic of uniswap pools is that anyone can create pools for any token pairs, thus if we dont fully validate each and every pool we are using, chances are there will be malicious entries hidden within them.
This is partially the case which we see here, the user gets to supply a path, where the source and target are validated against benign tokens, the intermediate ones are not. An example of utilizing path for arbitrary function call is illustrated below
In the above case, when transferring tokenM while doing swap, we have full control over code executed and can insert arbitrary contract calls within.
Noticeably, while gaining arbitrary contract calls sounds dangerous, it does not necessarily mean the contract is exploitable. It still depends on the scenario in which an arbitrary call happens.
In the case of duality, the two locations where arbitrary swapPath can be provided is in flashFocusCall and repayDebt, both in which holds a local lock over UniV3LpVault. No global are applied to Comptroller or Ctokens while performing swaps.
The lack of global locks here had us doubting whether an attack is possible. While we spent a considerable amount of time and failed to come up with any possible attack vectors, the complexity of the system held us back from concluding that an attack is impossible.
Thus we report this finding here in hope of inspiring developers either to prove the attack impossible or mitigate the attack surface.
vim, ganache-cli
The easiest way to mitigate this is to validate the entire path against a predefined whitelist while in _checkSwapPath. This approach is far from optimal and also limits the flexibility of swapping between tokens. However, before security is proved, this is the best approach we can come up with.
0xdramaone (Duality Focus) confirmed and commented:
Jack the Pug (judge) commented:
0xdramaone (Duality Focus) resolved
For this contest, 17 reports were submitted by wardens detailing low risk and non-critical issues. The report highlighted below by defsec received the top score from the judge.
The following wardens also submitted reports: rayn, IllIllI, sorrynotsorry, cmichel, Dravee, robee, 0xDjango, 0x1f8b, 0v3rf10w, cccz, kebabsec, bugwriter001, CertoraInc, hyh, samruna, and reassor.
