sherlock-audit / 2023-04-blueberry-judging

8 stars 5 forks source link

Ch_301 - Attacker could steal all the `borrowBalance` from Aura SPELL #100

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

Ch_301

high

Attacker could steal all the borrowBalance from Aura SPELL

Summary

When Aura SPELL gets to the third step to add liquidity on Balancer to get BPT tokens on openPositionFarm() at that point, the only token on the SPELL should param.borrowToken (except if a malicious user sends a dust amount for every token,...)

Vulnerability Detail

On these lines from openPositionFarm

            uint poolAmountFromA = (maxAmountsIn[0] * totalLPSupply) /
                balances[0];
            uint poolAmountFromB = (maxAmountsIn[1] * totalLPSupply) /
                balances[1];
            uint poolAmountOut = poolAmountFromA > poolAmountFromB
                ? poolAmountFromB
                : poolAmountFromA;

it is trying to find the amount of param.borrowToken
In case we have only one token param.borrowToken one of poolAmountFromA/poolAmountFromB should be zero e.g: Let's say poolAmountFromA == 10 and poolAmountFromB == 0 we need to get poolAmountOut == 10

we have 10 > 0 ==> true so poolAmountOut == poolAmountFromB which is zero

this will lead to outrunning this block

            if (poolAmountOut > 0) {//?@audit -this should revert if it false
                vault.joinPool(
                    poolId,
                    address(this),
                    address(this),
                    IBalancerVault.JoinPoolRequest(
                        tokens,
                        maxAmountsIn,
                        "",
                        false
                    )
                );
            }

To make this issue worse an attacker could send some BPT to the SPELL first and in case the user has (lend) a big amount as IsolatedCollateral and invoke openPositionFarm() all the borrowBalance will stay on the SPELL. an attacker could invoke closePositionFarm() to receive the borrowBalance from the SPELL by _doRefund() function

Impact

Code Snippet

Tool used

Manual Review

Recommendation

            uint poolAmountFromA = (maxAmountsIn[0] * totalLPSupply) /
                balances[0];
            uint poolAmountFromB = (maxAmountsIn[1] * totalLPSupply) /
                balances[1];
-            uint poolAmountOut = poolAmountFromA > poolAmountFromB
+            uint poolAmountOut = poolAmountFromA < poolAmountFromB
                ? poolAmountFromB
                : poolAmountFromA;

Duplicate of #46