Closed code423n4 closed 1 year ago
Contested, feels very autogenerated and is non-sensical in that conduits owned by EOAs are incredibly dangerous (like it would make more sense to require that a conduit is owned by a contract)
Agreed. Expected behaviour (and as pointed out, favourable) for a conduit to be owned by a SC instead of EOA.
HickupHH3 marked the issue as unsatisfactory: Insufficient proof
Lines of code
https://github.com/ProjectOpenSea/seaport/blob/5de7302bc773d9821ba4759e47fc981680911ea0/contracts/conduit/ConduitController.sol#L56
Vulnerability details
Bug Description
The createConduit function in the ConduitController smart contract is responsible for deploying new conduits, or contracts that allow registered callers (or open "channels") to transfer approved
ERC20/721/1155
tokens on their behalf. The function takes two parameters:conduitKey
andinitialOwner
. TheconduitKey
is used to deploy the conduit, and theinitialOwner
is set as the owner of the newly deployed conduit.The vulnerability lies in the fact that the
createConduit
function does not check if theinitialOwner
address passed as a parameter is a smart contract or not. This means that a malicious actor can create a conduit with a smart contract address as the initial owner, and then use that smart contract to perform malicious actions such as stealing assets that are transferred through the conduit, changing the behavior of the conduit, stealing any assets that are stored in the conduit.A malicious actor would exploit the lack of check for the smart contract in the
createConduit
function by creating a conduit with a smart contract address as the initial owner. The malicious actor would do this by calling thecreateConduit
function and passing the address of a smart contract that they control as theinitialOwner
parameter.Once the conduit is created, the smart contract address is set as the owner of the conduit and can perform any action that the owner of the conduit can perform.
The malicious actor can then use the smart contract to perform malicious actions such as:
Stealing assets that are transferred through the conduit by opening channels with other parties and then stealing assets via these channels.
Changing the behavior of the conduit by modifying the smart contract and making it perform malicious actions stealing any assets that are stored in the conduit (if the conduit is a storage contract)
Using the conduit to perform malicious actions
In this way, the malicious actor can steal assets that are transferred through the conduit, and also can use the conduit to perform other malicious actions.
It's important to note that the malicious actor can perform the attack by creating a conduit for any party, not just for himself. The malicious can create a conduit for any other party, set the smart contract as the owner of the conduit, and then use the smart contract to perform malicious actions.
The specific line of code that allows for the Smart Contract Initial Owner Vulnerability is the following:
This line of code is checking if the
initialOwner
is the null address(address(0))
and if so, it reverts the function call with an error messageInvalidInitialOwner
. However, it does not check if theinitialOwner
is a smart contract or not. So a malicious actor can create a conduit with a smart contract address as the initial owner, and then use that smart contract to perform malicious actions.Impact
The impact of this vulnerability can be severe, as the attacker can steal assets that are transferred through the conduit, and also use the conduit to perform other malicious actions. Additionally, the vulnerability can be exploited by an attacker who is already the owner of the conduit, by calling the
createConduit
function and passing a smart contract address as the initial owner, and then use the smart contract to perform malicious actions.Proof of Concept
A proof-of-concept (POC) code that demonstrates the presence of the Smart Contract Initial Owner Vulnerability in the ConduitController smart contract can be implemented as follows:
Create a smart contract, for example a malicious contract, that will be used as the initial owner for the conduit. This smart contract should have a function that allows an attacker to steal assets that are transferred through the conduit.
Create an instance of the
ConduitController
smart contract, and call thecreateConduit
function, passing the address of the malicious contract created in step 1 as the initial owner.Use the instance of the
ConduitController
smart contract to transfer assets through the conduit created in step 2, and check if the assets are stolen by the malicious contract.Here's a possible implementation of the POC code:
In this POC, the
Malicious
contract is used as the initial owner for the conduit. Theexploit()
function in the POC contract transfers assets to the conduit, which then gets stolen by theMalicious
contract due to the lack of a check for smart contract initial owners in theConduitController
contract.Recommended Mitigation Steps
To prevent this vulnerability, an additional check should be added to the createConduit function to verify that the
initialOwner
address passed as a parameter is not a smart contract. This check can be done by calling theisContract()
function provided by the Solidity address library, which returns a boolean indicating whether the given address is a smart contract or not.The following code snippet should be added to check if the
initialOwner
is a smart contract address or not:By adding this check, the function would revert if the initialOwner is a smart contract address, and prevent the vulnerability.