Beanstalk Notion
Beanstalk Notion
/
🪲
Bug Reports
/
BIC Notes
/
📄
Report #12593
📄

Report #12593

Report Date
October 20, 2022
Status
Closed
Payout

Critical: Take funds by changing Fee Receiver Address

‣
Report Info

Report ID

#12593

Target

https://etherscan.io/address/0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5

Report type

Smart Contract

Impacts

Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Has PoC?

Yes

Details

Missing access control allows to change the fee receiver address on admin contract.

Vulnerable Admin Contract

https://etherscan.io/address/0x8CF8Af108B3B46DDC6AD596aebb917E053F0D72b#writeContract

Fix

Add this line of code

    assert msg.sender == self.parameter_admin

Proof of concept

Visit here

  1. https://etherscan.io/token/0xc9c32cd16bf7efb85ff14e0c8603cc90f6f2ee49#readContract
  2. It has admin https://etherscan.io/address/0x8CF8Af108B3B46DDC6AD596aebb917E053F0D72b#writeContract
  3. Check this function
@external
def set_fee_receiver(_target: address, _base_pool: address, _fee_receiver: address):
    Factory(_target).set_fee_receiver(_base_pool, _fee_receiver)
  1. This function missed the owner check, allows anyone to set the fee receiver.

Exploit

  1. On this contract https://etherscan.io/address/0x8CF8Af108B3B46DDC6AD596aebb917E053F0D72b#writeContract

Attacker will call set_fee_receiver and change the fee receiver.

@external
def set_fee_receiver(_target: address, _base_pool: address, _fee_receiver: address):
    Factory(_target).set_fee_receiver(_base_pool, _fee_receiver)
  1. Then Attacker will call withdraw_admin_fees on this contract https://etherscan.io/token/0xc9c32cd16bf7efb85ff14e0c8603cc90f6f2ee49
  1. As you can see the code
Factory(factory).fee_receiver(BASE_POOL)
ERC20(coin).transfer(receiver, amount)
  1. It transfers funds to fee recieved address which has been already modified by attacker above.
  2. Finally attacker get all funds lying in the smart contract which are about $13996054 BEAN and $13673098 CURVEFI 3CRV.

BIC Response

This submission is related to an out of scope asset: the BEAN:3CRV Curve LP token. Curve pools are not part of Beanstalk and thus not included in the Immunefi bug bounty program. Curve pools are also non-upgradable.

The Beanstalk DAO acknowledges the risk of using Curve and has transparently communicated that here:

https://docs.bean.money/disclosures#12-curve-risk

Due to these reasons, this report is not eligible for a reward.

def withdraw_admin_fees():
    factory: address = self.factory

    # transfer coin 0 to Factory and call `convert_fees` to swap it for coin 1
    coin: address = self.coins[0]
    amount: uint256 = ERC20(coin).balanceOf(self) - self.balances[0]
    if amount > 0:
        ERC20(coin).transfer(factory, amount)
        Factory(factory).convert_fees()

    # transfer coin 1 to the receiver
    coin = self.coins[1]
    amount = ERC20(coin).balanceOf(self) - self.balances[1]
    if amount > 0:
        receiver: address = Factory(factory).fee_receiver(BASE_POOL)
        ERC20(coin).transfer(receiver, amount)