Reentrancy Vulnerability in Pipeline Contract
Report ID
#27228
Report type
Smart Contract
Has PoC?
Yes
Target
https://etherscan.io/address/0xb1bE0000C6B3C62749b5F0c92480146452D15423
Impacts
- Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Bug Description
The advancedPipe function in the Pipeline contract is vulnerable to a reentrancy attack due to the lack of a lock variable. This vulnerability allows an attacker to execute arbitrary code on the Pipeline contract by calling the advancedPipe function recursively before the first function call has finished executing. Even though the _advancedPipe function is declared as private, it is still possible for an attacker to call it multiple times using the DELEGATECALL opcode. This allows the attacker to bypass access restrictions and call the _advancedPipe function directly. This is because the DELEGATECALL opcode allows one contract to delegate the execution of a function call to another contract.
Impact
The reentrancy vulnerability in the Pipeline contract could allow an attacker to:
- Steal funds from the Pipeline contract.
- Manipulate the state of the Pipeline contract in other ways.
Risk Breakdown
Difficulty to Exploit: Easy Weakness: The vulnerability is due to lack of a lock variable in the advancedPipe function. This allows the function to be called recursively while it is still executing. CVSS2 Score: 9.1
Recommendation
the advancedPipe function should be modified to add a lock variable. This lock variable should be set to true before the function is executed and set to false after the function has finished executing. This will prevent the function from being called recursively while it is still executing.
function _advancedPipe( AdvancedPipeCall calldata p, bytes[] memory returnData ) private returns (bytes memory result) { require(!locked, "Pipeline: Reentrancy attack"); locked = true; uint256 value = getEthValue(p.clipboard); if (p.clipboard[0] == 0x00) { result = _pipe(p.target, p.callData, value); } else { result = LibFunction.useClipboard(p.callData, p.clipboard, returnData); result = _pipeMem(p.target, result, value); } locked = false; }
References
- Pipeline Documentation: https://evmpipeline.org/pipeline.pdf
- Reentrancy Attack: https://solidity-by-example.org/hacks/re-entrancy/
Proof of concept
// SPDX-License-Identifier: MIT pragma solidity 0.7.6;
contract Attacker { address pipeline;
}
// Main script contract Main { Pipeline pipeline;
constructor(Pipeline _pipeline) {
pipeline = _pipeline;
}
function exploit() external {
// Deploy the Attacker contract
Attacker attacker = new Attacker(address(pipeline));
// Call the attack function on the Attacker contract
attacker.attack();
}BIC Response
This is not a valid bug report because Pipeline is not a contract that generally stores assets, and thus there are no assets to steal as a result of this reported vulnerability. Any funds left in Pipeline are a result of misuse.