Submitted by 0xA5DF, also found by Lambda and V\B_
https://github.com/PartyDAO/party-contracts-c4/blob/3896577b8f0fa16cba129dc2867aba786b730c1b/contracts/crowdfund/Crowdfund.sol#L275
https://github.com/PartyDAO/party-contracts-c4/blob/3896577b8f0fa16cba129dc2867aba786b730c1b/contracts/crowdfund/Crowdfund.sol#L325
https://github.com/PartyDAO/party-contracts-c4/blob/3896577b8f0fa16cba129dc2867aba786b730c1b/contracts/distribution/TokenDistributor.sol#L26
At 2 places in the code only part of the output of keccak256() is used as the hash:
15/16 bytes hash is already not very high to begin with (as explained below). On top of that, using a non standard hash can be unsafe. Since diverging from the standard can break things.
For the FixedGovernanceOpts an attacker can create a legitimate party, and then when running buy() use the malicious hash to:
For the DistributionInfo struct - an attacker can easily drain all funds from the token distribution contract, by using the legitimate hash to create a distribution with a malicious ERC20 token (and a malicious party contract), and then using the malicious hash to claim assets of a legitimate token.
Using the birthday attack, for a 50% chance with a 15 bytes hash, the number of hashes needed to generate is 1.4e18 ((ln(1/0.5) *2) ** 0.5 * (2 ** 60)).
An attacker can create 2 different structs, a legitimate and a malicious one, while modifying at each iteration only the last bits
The attacker will than generate half of the hashes from the malicious one, and half from the legitimate ones, so in case of a collision theres a 50% chance itd be between the legitimate and malicious struct.
32 * 1.4e18 = ~4.5e19 bytes is needed, while an affordable drive can be 8TB=~8e12 bytes.
That puts it about 5e6 times away from and affordable attack.
The calculations above are for basic equipment, an attacker can be spending more on equipment to get closer (Id say you can easily multiply that by 100 for a medium size attacker + running the computations for more than one day).
Combining that with the fact that a non-standard hash is used, and that in general hashes can have small vulnerabilities that lower a bit their strength - Id argue its not very safe to be ~1e4 (for a medium size attacker; ~1.5e5 for 16 bytes) away from a practical attack.
Use the standard, 32-bytes, output of keccak256().
merklejerk (PartyDAO) confirmed and commented:
HardlyDifficult (judge) commented:
0xble (PartyDAO) resolved:
