Skip to content

Latest commit

 

History

History
72 lines (48 loc) · 4.98 KB

070.md

File metadata and controls

72 lines (48 loc) · 4.98 KB

Abundant Alabaster Toad

High

Anyone can delete same order twice will also delete other user orders

Summary

In DebitaLendOffer-Implementation.sol and DebitaBorrowOffer-Implementation.sol. Removing active order right after external call will allow attacker to remove their own order twice through reentrancy attack.

Under several attack path below, some active orders will be removed from active order list despite still active.

Root Cause

Standard reentrancy attack pattern. Change after unsafe external call.

internal pre-conditions

  • DebitaLendOfferFactory.sol have several active lending orders.
  • activeOrdersCount > 1

External pre-conditions

  • Assuming Attacker prepare lend order, borrow order so Aggregator contract accept borrow,lending offer include a malicous ERC20/ERC721 token as principle token.
  • Attacker can freely call acceptLendingOffer() and acceptBorrowOffer() with their own order through AggregatorV3.
  • Custom ERC20, ERC721 can reentrancy at specific point, right before delete order. Here

Attack Path

This demonstrate only Lend Order, Borrow Order have similar attack path.

To delete same order twice. You need to follow these basic steps:

  • attacker call DLOFactory.createLendOrder() to create order with custom token address, with lending amount = 100e18
  • attacker craft Aggregator instruction to call order implementation DLOImplementation.acceptLendingOffer() with half amount 50e18.
  • During first call, availableAmount is reduced by 50e18. Here
  • After lendInformation.availableAmount -= amount;, the available amount still 50e18 lendInformation.availableAmount = 50e18.
  • During token transfer phase, reentrancy call cancelOffer() immediately. Here
  • Because lendInformation.availableAmount > 0 still true, with 50e18 availableAmount. The call only require owner to manually call. This is doable for attacker.
  • Cancel order reset availableAmount to zero. lendInformation.availableAmount = 0
  • DLOImplementation.cancelOffer() now delete order first time.
  • Exit reentrancy call. Back to previous Token transfer reentrancy point DLOImplementation.acceptLendingOffer().
  • The check if (lendInformation.availableAmount == 0) read from storage directly, which availableAmount will be zero here.
  • Delete order is called second time.
  • Factory will try to delete order with zero index, which is not attacker order.

First delete, remove attacker order. Second delete, remove user order at index 0. Order before attacker will moved from last place to first place (index 0).

Impact

Repeat attack path above multiple times, attacker can remove entire active order list.

This list is required to allow web user access their active order. Without this list, user will have to manually find their order contract address through events. Which is unlikely, leads to reputation lost and website operation down until fixed.

PoC

Mitigation

Move all external calls (Token transfer) to the end of function.