# Crosswise MasterChef: trusted forwarder spoof drains WBNB

Crosswise MasterChef's public setTrustedForwarder let the attacker spoof owner/staker via calldata-suffix _msgSender, setting 100% deposit fee and draining 4.16 WBNB.

- Payout: Real-world hack
- Severity: high
- Program: Crosswise
- Credited: DeFiHackLabs
- Disclosed: 2025-05-06
- Write-up quality: 8/10
- Original: https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-05/crosswise_exp.sol
- Library page: https://bugbountylibrary.com/r/dhl%3A20250506-crosswise
- Tags: domain:web3 impact:funds-loss kind:incident platform:defihacklabs sev:high tech:evm technique:source-review vuln:access-control vuln:auth-bypass vuln:business-logic

**Target:** MasterChef staking contract (BSC)
**Root cause:** setTrustedForwarder is callable by anyone, and _msgSender() trusts a calldata-suffix address appended by the trusted forwarder, so any caller can impersonate arbitrary senders.
**Steps:**
1. Call `setTrustedForwarder(address(this))` on MasterChef to become the trusted forwarder.
2. Append `bytes20(owner)` to calldata and call `set(0,0,10000,address(0),false)` to set pool 0 deposit fee to 100%.
3. Call `updatePool(0)`; spoof dev and treasury to keep fee routing intact via `setDevAddress`/`setTreasuryAddress`.
4. Append `bytes20(SPOOFED_STAKER)` and call `deposit(0, stakerBalance, address(0), false, false)` to move the staker's approved CRSS into the pool.
5. Deposit fee sends CRSS into the CRSS/WBNB pair; compute amountOut and call `pair.swap(0, amountOut, attacker, '')` to extract WBNB.
**How found:** Recognized that setTrustedForwarder is unauthenticated and that _msgSender() derives sender from a calldata suffix, enabling impersonation of owner and any approved staker.
**Exploitation:** Attacker becomes trusted forwarder, spoofs owner to set 100% deposit fee, spoofs an approved staker to deposit their CRSS, fee is routed to the CRSS/WBNB pair, then swaps out 4.16 WBNB.
**Insight:** When a contract uses ERC2771-style calldata-suffix _msgSender(), check whether the trusted forwarder setter is access-controlled; if not, every privileged function becomes callable as anyone.
