Closed rajatbeladiya closed 1 year ago
Borrow allowance has two arguments in the state variable. The receiver
of the borrowed amount, and the operator
(an address that is allowed to execute the operation). In the described scenario, Alice will have to approve the "attacker" as the receiver, which would not make sense from a user point of view.
Refer to v0.0.1 reviewed during audit competition.
This issue is dismissed.
Affected smart contract:
BaseRouter.sol BorrowingVault.sol ConnextRouter.sol SimpleRouter.sol
Severity:
High
Impact:
users debt asset can be stolen and debtToken will be minted to user
Description:
Note:
BaseRouter.sol
inhereted toConnextRouter.sol
andSimpleRouter.sol
so both contracts are vulnerable and hereBaseRouter.sol
considered asConnextRouter.sol
andSimpleRouter.sol
https://github.com/Fujicracy/fuji-v2/blob/50fd0b74ccee1a73a459118e50e044a2bcfacd10/packages/protocol/src/vaults/borrowing/BorrowingVault.sol#L221-L239
BorrowingVault.sol => here user can borrow if user self want to borrow or user give
_spendBorrowAllowance
to other user to borrow.BaseRouter.sol =>
xBundle()
internally called calls_bundleInternal()
which takesactions[]
andargs[]
from user and it is also can be used to borrow funds fromBorrowingVault.sol
.if user execute borrow from this function user needs to give
_spendBorrowAllowance
toBaseRouter.sol
.https://github.com/Fujicracy/fuji-v2/blob/50fd0b74ccee1a73a459118e50e044a2bcfacd10/packages/protocol/src/abstracts/BaseRouter.sol#L157-L165
here Borrow Action calls
BorrowingVault.sol
’s borrow() function, where it is checked if (caller != owner) it will check_spendAllowance
https://github.com/Fujicracy/fuji-v2/blob/50fd0b74ccee1a73a459118e50e044a2bcfacd10/packages/protocol/src/vaults/borrowing/BorrowingVault.sol#L231-L233
in this case
caller
will beBaseRouter.sol
andowner
will beuser
Suppose,
Alice gives MAX
_spendBorrowAllowance
toBaseRouter.sol
and borrow 1 token usingxBundle()
and PayBack, still remaining_spendBorrowAllowance
will be large.So, Attacker can call
xBundle()
function with args asowner = address(Alice), receiver = address(Attacker), amount = (Alice’s max allowed borrow amount)
Borrow action will be executed and
debtAsset
will be transfer to Attacker anddebtShare
will be minted to AliceAttacke scenario:
_spendBorrowAllowance
to MAX or larger than he actually borrowsxBundle()
and PayBack => noDebt right nowxBundle()
function withBorrow Action
and args =>receiver = address(attacker)
,owner = address(Alice) amount = (Alice’s max allowed borrow amount)
Recommended Mitigation Steps:
add check at
BaseRouter.sol
thatmsg.sender
isowner
or you need to change logic toborrow
function ofBorrowingVault.sol