HardhatDeFi
15,000 USDC
View results
Submission Details
Severity: high
Invalid

Unchecked External Calls to Untrusted Contracts

Summary

External calls to untrusted contracts (such as the calls made to external smart contracts, e.g., IDIVA(_diva).redeemPositionToken() and IAave(_aaveV3Pool).withdraw()) can potentially be used for reentrancy attacks if not handled correctly. This happens when an external contract makes a callback into the calling contract, potentially causing unexpected behavior, including fund theft or other exploits.

Vulnerability Details

In the contract AaveDIVAWrapperCore.sol, calls are made to external contracts without any reentrancy guard. Specifically, the functions _redeemPositionToken line 253 and _redeemWToken line 311 make calls to external contracts (_diva and _aaveV3Pool) to redeem tokens and withdraw collateral. These external calls could trigger unexpected behaviors if the external contract is malicious or compromised. If these calls are made to contracts that can reenter into the AaveDIVAWrapper contract (through callbacks), malicious actors might exploit this to drain funds or cause unexpected state changes.

This vulnerability is common if state-changing operations (e.g., transfers, withdrawals) are made after external calls.

Impact

  • Potential Fund Loss: If the external contract is malicious or has been compromised, it can reenter and manipulate the state of the contract. This could result in unauthorized transfers of funds or other unexpected outcomes.

  • Protocol Downtime or Malfunction: The absence of protection mechanisms like reentrancy guards can cause inconsistent contract states or break expected contract behavior, leading to losses or downtime.

Proof of Concept (PoC)

Overview:

This PoC demonstrates how an attacker might exploit the unchecked external calls in the contract for a reentrancy attack.

Actors:

  • Attacker: The malicious contract that exploits the vulnerability.

  • Victim: The user who interacts with the AaveDIVAWrapper contract.

  • Protocol: The AaveDIVAWrapper contract and any external protocols (like Aave and DIVA) that are being called.

Working Test Case:

// Solidity test case demonstrating the reentrancy vulnerability
// Attack contract
contract AttackContract {
address targetContract; // The AaveDIVAWrapper contract to exploit
address victim; // The victim user
// The attacker calls the target contract
function exploit() public {
targetContract.call(abi.encodeWithSignature("redeemPositionToken(address,uint256,address)", address(this), 100, victim));
}
// The fallback function gets triggered upon calling the external contract
fallback() external payable {
// Reenter into the target contract and exploit it (e.g., withdraw funds again or manipulate state)
AaveDIVAWrapper(targetContract).redeemPositionToken(address(this), 100, victim);
}
// Attacker initiates the exploit, causing the contract to call back
function startExploit(address _targetContract, address _victim) external {
targetContract = _targetContract;
victim = _victim;
exploit();
}
}
// The victim contract will interact with the vulnerable contract
contract VictimContract {
AaveDIVAWrapper protocol; // The vulnerable contract
constructor(address _protocol) {
protocol = AaveDIVAWrapper(_protocol);
}
// Victim interacts with the vulnerable contract
function redeemTokens(address _positionToken, uint256 _amount) public {
protocol.redeemPositionToken(_positionToken, _amount, msg.sender);
}
}

Line-by-Line Explanation:

  1. Attack Contract Setup:

    • The attacker sets up a contract with the target contract's address and victim's address.

    • The attacker can call the vulnerable function redeemPositionToken() on the AaveDIVAWrapper contract.

  2. Fallback Function:

    • The fallback function is triggered when the external call is made to the attacker's contract, allowing the attacker to reenter the redeemPositionToken function again.

  3. Exploit Scenario:

    • The attacker calls startExploit(), which invokes exploit() to call the vulnerable contract function.

    • On the external call to redeemPositionToken, the attacker is able to reenter the same function, potentially causing the contract to make a second withdrawal before the state is updated.

Outcome:

  • If successful, the attacker can reenter the contract and potentially withdraw additional funds or manipulate the contract state, causing inconsistent behavior.

Implications:

  • The attacker can drain funds from the protocol by repeatedly reentering the vulnerable function before the contract's state is updated.

  • If funds are not properly protected, the attacker can steal collateral or manipulate the contract.

Mitigation Plan:

  1. Reentrancy Guard:

  • The contract can implement a reentrancy guard to prevent reentrancy attacks.

Example:

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract AaveDIVAWrapper is ReentrancyGuard {
// Use nonReentrant modifier to prevent reentrancy attacks
function _redeemPositionToken(...) external nonReentrant {
// function logic
}
}

2 Checks-Effects-Interactions Pattern:

  • The contract should update the state (e.g., balances) before calling external contracts. This reduces the risk of an attacker manipulating the state after the external call.

Example:

function _redeemPositionToken(...) external {
// Update state first (e.g., update balances, allowances)
uint256 amountToRedeem = ...;
// External call to redeem token
externalContract.redeem(amountToRedeem);
}

By applying these mitigations, we can prevent the vulnerability from being exploited by external attackers.

Tools Used

  • Manual code review

Recommendations

Recommended Mitigation:

  1. Reentrancy Guard: Use a reentrancy guard (e.g., OpenZeppelin's ReentrancyGuard) to prevent reentrancy attacks. This will stop an external contract from calling back into the contract before the original function has completed.

  2. Checks-Effects-Interactions Pattern: Rearrange the logic to follow the "checks-effects-interactions" pattern, which ensures that all state changes (e.g., balances, approvals) are done before making any external calls.

  3. Limit External Calls: If possible, reduce the number of external calls or replace them with more secure, internal contract logic.

Updates

Lead Judging Commences

bube Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.