Snowman Merkle Airdrop

AI First Flight #10
Beginner FriendlyFoundrySolidityNFT
EXP
View results
Submission Details
Impact: high
Likelihood: low
Invalid

[H-01] Potential Hash Collision via abi.encodePacked with Dynamic Types

Summary

The contract Snowman.sol utilizes abi.encodePacked() with multiple dynamic arguments within a keccak256() hash function, which can lead to hash collisions.

Vulnerability Detail

In src/Snowman.sol at lines 54 and 57, the code uses abi.encodePacked() to concatenate data before hashing it. When abi.encodePacked() is used with multiple dynamic types (such as string or bytes), it does not include any padding between the elements.

This lack of padding allows different sets of input data to produce the exact same output hash. For example, the following two distinct inputs will result in a collision:

  • keccak256(abi.encodePacked("a", "bc"))

  • keccak256(abi.encodePacked("ab", "c"))

Both operations result in the same concatenated bytes before hashing, leading to an identical bytes32 result.

Impact

  • A malicious actor could exploit this collision to bypass security checks or provide fraudulent data that matches an existing hash. In the context of Merkle trees or signatures, this could allow for the creation of unauthorized proofs.

Proof of Concept (PoC)

To demonstrate the collision, you can run a simple Chisel session or a Foundry test:

function testHashCollision() public pure {
bytes32 hash1 = keccak256(abi.encodePacked("a", "bc"));
bytes32 hash2 = keccak256(abi.encodePacked("ab", "c"));
assert(hash1 == hash2); // This will pass, proving the collision
}

Recommended Mitigation

Replace abi.encodePacked() with abi.encode(), which implements proper padding to 32 bytes for each argument, thereby ensuring unique hash outputs for unique inputs. Alternatively, for concatenating only strings or bytes, consider using bytes.concat().

// src/Snowman.sol
bytes32 hash = keccak256(abi.encode(part1, part2));
}

Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 11 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!