TLDR; I discovered a misconfiguration for a collateral with weak oracle on lending & borrowing platform, combine with a nuance in collateral value counting logic between borrow and withdraw, an attacker can use this asset as collateral, inflate the price then default on a loan taking free money
Sturdy is a lending & borrowing platform on Fantom, inspired from Aave (most of its codebase are forked from Aave). Though, there are certain distinctions, it is not relevant to my finding. You can read more about Sturdy on their documentation.
Also inspired from another fellow hacker(s) Hackxyk, from their recent finding on Aave about a misconfiguration of fallback oracle that could allow attacker to manipulate the price of an asset used in Aave (Read more about this in their twitter thread: https://twitter.com/Hacxyk/status/1519311459938824193)
I decided to look for the same type of mistake on other lending & borrowing platforms and found something interesting on Sturdy.
In their LendingPool contract, I noticed that there are more assets listed than those meet the eye.
One that stood out to me was an LP token on TombSwap “TOMB-MAI”. Then, I traced it further to its oracle address and found that it used this oracle: TombMiMaticLPOracle.sol
It seemed like a legit oracle, given that it’s intended to use cumulative price… then I peek at the latest transaction to this contract, and surprisingly enableCumulative was disabled, 2 hours after it was enabled.
Therefore, instead of cumulative price, it used another known weak mechanism, by calculating the spot price from pool reserve.
Although the oracle was weak, but was it exploitable? maybe this asset was listed, but disabled through configurator, meaning I needed to look further.
Disappointed at first, when I saw this transaction https://ftmscan.com/tx/0xad60a78afbcb66066e5191578fe795f194d73366f196c7c2dd7fb81ec0eb0c0e
The above transaction set LTV=0, liquidationThreshold=7500, liquidationBonus=10750 for “TOMB-MAI LP”.
I thought that with LTV=0, this asset could not be used as a collateral to borrow other assets. So, even with weak oracle settings, it’s not exploitable.
See this logic in validateBorrow function, https://github.com/sturdyfi/sturdy-contracts/blob/main/contracts/protocol/libraries/logic/ValidationLogic.sol#L182
If LTV=0, it would fail from division by zero. You can deposit multiple collaterals as well, but LTV=0 would bring your averageLTV down, thus, less collateral value.
But then, while reading through their codes on GitHub, I found that withdraw operation used a slightly different logic to validate whether user can withdraw their collateral or not comparing to their current debt value.
It counts all collaterals with liquidationThreshold > 0 as collateral value, ignoring LTV . Meaning, “TOMB-MAI LP” is also counted as collateral, when user performs a withdrawal operation.
With the validation logic from withdrawal function, and a weak oracle. It’s indeed exploitable
Here is how an attack could work
(1) Attacker deposits a collateral with LTV > 0 and borrows other assets against it.
(2) Attacker gets TOMB-MAI LP, then deposits to the pool.
(3) Attacker manipulate the price of TOMB-MAI LP (swap a large amount of MAI into the pool)
(4) Attacker withdraw their collateral in (1)
(5) Swap back MAI, resume the price, and default the loan.
So, for an asset to be disabled, or used as collateral, liquidationThreshold should be set to 0 too.
I reported this on May 2, 2022 with a PoC to demonstrate the attack.
Team responded in 2 hrs, and started fixing the issue.
3m USD worths of stablecoin were at risk. Hence, the critical severity with maximum impact.
May 2, 2022 at 2:36 am — Report sent
May 2, 2022 at 2:48 am — Triaged & Escalated by ImmuneFi
May 2, 2022 at 4:21 am — Team responded, froze affected assets
May 11, 2022 at 1:11 am — Bounty paid for Critical