Closed code423n4 closed 1 year ago
contested on both counts; we mask all lengths and pointers on the way in which prevents an attacker from even passing in an array length large enough to overflow any for loops; and an attacker sending Ether in is simply donating their eth to the caller to use at their discretion
Insufficient proof on:
terminalMemoryOffset
being large enough to cause DoSHickupHH3 marked the issue as unsatisfactory: Insufficient proof
Lines of code
https://github.com/ProjectOpenSea/seaport/blob/5de7302bc773d9821ba4759e47fc981680911ea0/contracts/lib/OrderCombiner.sol#L447-L482 https://github.com/ProjectOpenSea/seaport/blob/5de7302bc773d9821ba4759e47fc981680911ea0/contracts/lib/OrderCombiner.sol#L725-L728 https://github.com/ProjectOpenSea/seaport/blob/5de7302bc773d9821ba4759e47fc981680911ea0/contracts/lib/OrderCombiner.sol#L706-L713
Vulnerability details
Impact
Use of
unchecked
in-for loops.selfbalance()
function in_performFinalChecksAndExecuteOrders
function.Use of the
unchecked
keyword in several places in the code, specifically for loops and the_transfer function
. This keyword is used to suppress overflow/underflow checks in Solidity, and its use can make the contract susceptible to attacks that exploit these conditions, a malicious actor could manipulate the input data to a for loop to cause it to run an excessive number of iterations, potentially causing the contract to run out of gas or execute unintended actions.Use of the
selfbalance()
function in the_performFinalChecksAndExecuteOrders
function. Theselfbalance()
function is used to retrieve the balance of the contract's own account, and its use can be exploited by malicious actors to manipulate the contract's behavior, anattacker
could increase the contract's balance by sending a large amount of Ether to it, and then use this increased balance to perform unauthorized actions.Proof of Concept
Exploit the use of
unchecked
in the forloops
by creating amalicious contract
that sends a large number of orders to the target contract. Theloops
that iterate over these orders do not have any overflow checks, allowing the attacker to overflow the index and access memory outside of the intended range. This will lead to unintended data access, or even worse, data modification.Code.
An attacker can exploit the use of
selfbalance()
function in_performFinalChecksAndExecuteOrders
function by creating a malicious contract that manipulates the balance of the target contract, thus allowing the attacker to pass the check and get more token than they should have.Code.
In both
PoC, the attacker
causes unintended behavior in the target contract, leading to loss of funds, or unauthorized access to data.Tools Used
Manual audit.
Recommended Mitigation Steps
For the
unchecked
keyword in for loops, the developer should add overflow checks in the for loops by replacing the unchecked keyword with a check for the loop variable being less than the maximum value. For example, instead of usingunchecked { for (uint256 i = 0; i < advancedOrders.length; ++i) {" the developer should use "for (uint256 i = 0; i < advancedOrders.length && i < uint256(2**256 -1); ++i) {
Add
require(accumulator.length + 32 <= AccumulatorMaxLength,"Accumulator overflow");
before the transfer function.As for the
selfbalance()
function in the_performFinalChecksAndExecuteOrders
function, the developer can usemsg.value
instead ofselfbalance()
function. This will allow the developer to check the balance of the address that is calling the contract rather than the contract's own balance.Code.