Evidently the method used in this deployment is CREATE2
Problem however is that this method of creating the pool address leaves it vulnerable to a pool collision attack, which would then make anyone possible to take the funds from the target assertion.
From the above, when deploying we can see that the salt value is 0, and then the rollup and the _assertionHash, so to collide an attacker just needs to have access to these data, now for rollups these are easily gotten, however for the assertionHash, an attacker can just brute-force and deploy as much pool contracts as possible so as to get funds from the ones that would be valid.
So by brute forcing the attacker in this can create multiple staking pool contracts for a rollUp.
So an attacker can find multiple adresses for pool in which could collide with the pools to be created in the future. Now for a classic brute-force-based attack in cryptography:
Since salt is 0, brute-force a sufficient number of values for the assertion hash for a rollup, pre-compute the resulting addresses, and efficiently store them e.g. in a Bloom filter data structure.
The feasibility and detailed technique, along with the hardware requirements for finding a collision, are well-documented in multiple references:
The BTC network's hashrate has reached around 7x10^20 hashes per second as of the time of writing, which takes around 3o minutes to achieve 2^80 hashes. Even a fraction of this computing power can easily find a collision in a reasonably short timeframe.
EIP-3607 whose rationale addresses this exact attack. The EIP is in its final state.
A blog post discussing the cost (both in money and time) of this exact attack.
So assuming the attacker has already found address collision against a potential undeployed assertion/staking Pool, let's say 0xASP. The steps for complete draining of the Pool in the future are as follow:
Deploy the attack contract onto address 0xASP.
Attach a functionality to increase the allowance for {0xASP ---> attacker wallet} for any token they want, which in this case would be the staking token that's attached to the assertion when it gets finalized.
This way the attacker now has complete control of any funds sent to 0xASP.
NB: The runnable-POC is not directly the case in this instance however it does show how the collision would occur which is useful to understand this report.
Impact
Address collision can cause all tokens attached to a specific assertion to be stolen.
Don't use a constant salt value, and have it msg.sender provided instead, this way am attacker can't guess who's going to be deploying the target assertion.
Lines of code
ttps://github.com/code-423n4/2024-05-arbitrum-foundation/blob/6f861c85b281a29f04daacfe17a2099d7dad5f8f/src/assertionStakingPool/AssertionStakingPoolCreator.sol#L12-L23
Vulnerability details
Proof of Concept
Take a look at https://github.com/code-423n4/2024-05-arbitrum-foundation/blob/6f861c85b281a29f04daacfe17a2099d7dad5f8f/src/assertionStakingPool/StakingPoolCreatorUtils.sol#L13-L21
This function is used to get the staking pool deployed with provided inputs and should revert if pool contract doesn't exist.
Note that all other instances querying pools, end up calling this function as can be confirmed by this search command: https://github.com/search?q=repo%3Acode-423n4%2F2024-05-arbitrum-foundation+getPool+NOT+language%3AMarkdown&type=code.
Here is how the staking pool contract is created for a target assertion, which is used for any child Arbitrum chain running on top of the deployed AssertionStakingPoolCreator's chain. https://github.com/code-423n4/2024-05-arbitrum-foundation/blob/6f861c85b281a29f04daacfe17a2099d7dad5f8f/src/assertionStakingPool/AssertionStakingPoolCreator.sol#L12-L23
Evidently the method used in this deployment is
CREATE2
Problem however is that this method of creating the pool address leaves it vulnerable to a pool collision attack, which would then make anyone possible to take the funds from the target assertion.Note: This report is very highly inspired from this past valid report.
From the above, when deploying we can see that the salt value is 0, and then the
rollup
and the_assertionHash
, so to collide an attacker just needs to have access to these data, now for rollups these are easily gotten, however for the assertionHash, an attacker can just brute-force and deploy as much pool contracts as possible so as to get funds from the ones that would be valid.So by brute forcing the attacker in this can create multiple staking pool contracts for a rollUp.
So an attacker can find multiple adresses for pool in which could collide with the pools to be created in the future. Now for a classic brute-force-based attack in cryptography:
0
, brute-force a sufficient number of values for the assertion hash for a rollup, pre-compute the resulting addresses, and efficiently store them e.g. in a Bloom filter data structure.The feasibility and detailed technique, along with the hardware requirements for finding a collision, are well-documented in multiple references:
The BTC network's hashrate has reached around 7x10^20 hashes per second as of the time of writing, which takes around 3o minutes to achieve 2^80 hashes. Even a fraction of this computing power can easily find a collision in a reasonably short timeframe.
So assuming the attacker has already found address collision against a potential undeployed assertion/staking Pool, let's say 0xASP. The steps for complete draining of the Pool in the future are as follow:
More details about this issue and a can be seen from this linked report, whose runnable POC is here: https://gist.github.com/midori-fuse/087aa3248da114a0712757348fcce814, with steps ti run it attached in the report.
Impact
Address collision can cause all tokens attached to a specific assertion to be stolen.
Tool Used
Recommended Mitigation Steps
Don't use a constant
salt
value, and have itmsg.sender
provided instead, this way am attacker can't guess who's going to be deploying the target assertion.#
Assessed type
Context