EgisSecurity - Exploiter can force user into unhealthy condition and liquidate him #299
Labels
Has Duplicates
A valid issue with 1+ other issues describing the same vulnerability
Medium
A Medium severity issue.
Reward
A payout will be made for this issue
Sponsor Confirmed
The sponsor acknowledged this issue is valid
Will Fix
The sponsor confirmed this issue will be fixed
EgisSecurity
High
Exploiter can force user into unhealthy condition and liquidate him
Summary
Protocol implements a flexible cross-margin portfolio managment with the help of
Position
smart contract, which should hold borrower's collateral and debt positions.Anyone can open a pool in the singleton
Pool
contract and chose valid collateral assets with corresponding LTV values by callingRiskEngine#requestLtvUpdate -> acceptLtvUpdate
. In the README it is stated that the bound for valid LTVs would be in the range 10%-98%There is a flaw in the way risk module calculates whether a position is healthy.
Root Cause
The problem roots is that
_getPositionAssetData
uses getAssetValue, which usesIERC20(asset).balanceOf(position)
to obtain the tokens for the given asset in user's position:Later, when we calculate the
minRequired
collateral for given debt, we use a wighted average tvl based on the weights in the user position:The problem is that expoiter may donate funds to user position with the collateral asset with the lowest LTV, which will manipulate _getMinReqAssetValue calculation and may force the user into liquidation, where the expoiter will collect the donated funds + user collateral + discount.
Internal pre-conditions
External pre-conditions
Nothing special
Attack Path
Imagine the following scenario:
We use $ based calculations for simplicity, but this does not matter for the exploit.
We also have simplified calculations to simple decimals (100% = 100) to remove unnececarry for this case complexity.
Precondition state:
Victim Position Asset Porfolio: [USDC = $1000; WBTC = $10]
Pool 1: [Leding Asset = DAI] [USDC tvl = 95%; WBTC tvl = 30%]
minReqAssetValue = (940 * 99 / 95) + (940 * 1 / 30) = 979 + 31 ~= $1 010
)minReqAssetValue
Attack beggins:
liquidate
, we entervalidateLiquidation
->isPositionHealthy
, where we get each asset value and weight:totalAssetValue = $2000
positinAssets = [USDC; WBTC]
,positionAssetWeight = [50; 50]
_getMinReqAssetValue
and we iterate two times for the single $940 debt and here is the resultminReqAssetValue += 940 * 50 / 95 = 494
minReqAssetValue += 940 * 50 / 30 = 1 566
494 + 1 566 = $2 060
, which is$60 > totalAssetValue
, which means that position is not healthy.Recommendation
Introduce virtual balance inside
position
, which is updated on deposit/withdraw actions. This will prevent manipulations of the weighted average tvl due to donations.Impact
Unfair liquidations, which in normal situations may never occur, result in the theft of user collateral.
PoC
No response
Mitigation
Introduce virtual balance inside position, which is updated on deposit/withdraw actions. This will prevent manipulations of the weighted average tvl due to donations.
The text was updated successfully, but these errors were encountered: