【SlowMist Analysis】Detailed analysis of the hacking incident on DeFi platform Lendf.Me and defense recommendations

share
【SlowMist Analysis】Detailed analysis of the hacking incident on DeFi platform Lendf.Me and defense recommendations

According to SlowMist Zone, the Ethereum DeFi platform Lendf.Me has suffered a re-entry vulnerability attack. The SlowMist security team promptly analyzed the attack upon receiving the information and quickly identified the issue.

According to the preliminary statistics and analysis of the anti-money laundering AML system of SlowMist Technology, the cumulative loss from the attack on Lendf.Me is approximately $24,696,616 USD. The specific cryptocurrencies and amounts stolen are:

WETH: 55159.02134,
WBTC: 9.01152,
CHAI: 77930.93433,
HBTC: 320.27714,
HUSD: 432162.90569,
BUSD: 480787.88767,
PAX: 587014.60367,
TUSD: 459794.38763,
USDC: 698916.40348,
USDT: 7180525.08156,
USDx: 510868.16067,
imBTC: 291.3471

Subsequently, the attacker continuously exchanged the stolen tokens for ETH and other tokens through DEX platforms such as 1inch.exchange, ParaSwap, Tokenlon, etc.

The following is a detailed analysis process.

Table of Contents

Attack Details

The attacker's address for the attack on Lendf.Me is 0xa9bf70a420d364e923c74448d9d817d3f2a77822, and the attacker launched the attack on Lendf.Me by deploying the contract 0x538359785a8d5ab1a741a0ba94f26a800759d91d.

By examining one of the attacker's transactions on Etherscan: https://etherscan.io/tx/0xae7d664bdfcc54220df4f18d339005c6faf6e62c9ca79c56387bc0389274363b

We found that the attacker first deposited 0.00021593 imBTC, but successfully withdrew 0.00043188 imBTC from Lendf.Me, nearly doubling the withdrawal amount compared to the deposit. How did the attacker manage to double the balance from a single transaction? This requires a detailed analysis of each action in the transaction to see what exactly happened.

By placing the transaction on bloxy.info, we can see the complete transaction flow.

Through analyzing the transaction flow, we can see that the attacker made two calls to the supply function in Lendf.Me, but these calls were independent and not nested within each other.

Subsequently, during the second call to the supply function, the attacker invoked the withdraw function from their own contract on Lendf.Me, ultimately making a withdrawal.

Here, we can analyze that the attacker's withdraw call occurred within the transferFrom function, which is when Lendf.Me calls the user's tokensToSend hook function through transferFrom. It is evident that the attacker re-entered the Lendf.Me contract through the supply function, causing a reentrancy attack. What are the specific details of the attack? Let's delve into the Lendf.Me contract code next.

Code Analysis

After a series of processing in the supply function of Lendf.Me, a doTransferIn function is called to deposit the user's provided tokens into the contract, followed by assigning some information to the market variable. Reflecting on the attack process mentioned earlier, the attacker made a withdrawal call through reentrancy in the second supply function. This means that operations after line 1590 in the second supply function are not executed until after the withdrawal is completed. These operations lead to an increase in the attacker's withdrawal balance.

Let's analyze the supply function in depth.

As shown in the above diagram, at the end of the supply function, updates are made to the market and user's balances. Prior to this, the user's balance is pre-fetched at the beginning of the function and stored in localResults.userSupplyCurrent, as follows:

By assigning to the localResults variable, the user's transfer information is temporarily stored in this variable. At this point, when the attacker executes the withdraw function, let's examine the code of the withdraw function:

There are two key points here:

1. At the beginning of the function, the contract first retrieves the market and supplyBalance variables from storage.

2. At the end of the withdraw function, the same logic updates the market and user's balance information supplyBalance, deducting the user's withdrawal amount from the balance.

In a normal withdrawal scenario, when the withdraw function is executed separately, the user's balance would be deducted and updated as usual. However, since the attacker embedded the withdraw function within supply, after updating the user's balance supplyBalance in the withdraw function, the subsequent code to be executed in the supply function, i.e., after line 1590, updates the user's balance again. The value used for the update will be the user's original deposit saved at the beginning of the supply function in localResults, plus the value of the attacker's initial deposit when calling the supply function for the first time.

Through this operation, although the user's balance has been deducted after the withdrawal, the logic in the supply function will overwrite the value of the balance that was not deducted, leading to an increase in the balance instead of a deduction. In this way, the attacker can make exponential withdrawals until draining Lendf.Me completely.

Defense Recommendations

For this attack incident, SlowMist Security Team suggests:

  1. Integrate locking mechanisms into critical business operations, such as OpenZeppelin's ReentrancyGuard.
  2. When developing contracts, follow the practice of first changing variables within the contract before making external calls.
  3. Prior to project launch, have an excellent third-party security team conduct a comprehensive security audit to identify potential security issues.
  4. When integrating multiple contracts, ensure code and business security checks are in place for all parties involved, considering security issues that may arise from various business scenarios.
  5. Set up pause switches in contracts whenever possible to promptly identify and mitigate in the event of a "black swan" incident.
  6. Security is dynamic, and project teams also need to promptly capture threat intelligence related to their projects and identify potential security risks in a timely manner.

Attachment:

OpenZeppelin ReentrancyGuard: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol

Original Article Link

Related Readings

  • 【Observation】Binance Sets BNB Burn Record in Q1, The Block's Critique and Honest Evaluation
  • 【Special】Most Fearful of Teachers Running Away: How Decentralized Protocols Address the Issue of Trust in Operation

Join Telegram now to get the most accurate blockchain news and cryptocurrency updates!