Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: medium
Invalid

Hash Collision Risk in `assertValidNonce` Due to Usage of `abi.encodePacked` with Dynamic Types

Summary

The assertValidNonce function in LLMOracleCoordinator.sol uses abi.encodePacked to generate a hash for nonce verification. The inputs to this encoding include dynamic types, specifically bytes data, which makes the function susceptible to hash collisions. This vulnerability may allow malicious users to bypass nonce validation by exploiting these collisions, potentially leading to task spoofing or replay attacks.

Vulnerability Detail

The assertValidNonce function relies on the following code to construct a message for hashing:

bytes memory message = abi.encodePacked(taskId, task.input, task.requester, msg.sender, nonce);
if (uint256(keccak256(message)) > type(uint256).max >> uint256(task.parameters.difficulty)) {
revert InvalidNonce(taskId, nonce);
}

The issue arises from the use of abi.encodePacked, which is known to be insecure when used with dynamic data types (like bytes). In this case, the input field within the TaskRequest struct is a bytes type, meaning that different input values could potentially produce the same hash when concatenated, leading to hash collisions.

Such collisions can enable malicious users to bypass nonce validation, leading to:

  • Replay Attacks: A malicious user might bypass nonce protection by crafting input data that yields the same hash as previously validated data.

  • Task Spoofing: A malicious user may submit invalid or spoofed tasks that are accepted as valid.

Root Cause

The use of abi.encodePacked to hash a mix of fixed and dynamic data types without explicit structuring opens up the function to hash collisions, as dynamic types are concatenated directly without length prefixes or separation markers.

Impact

If exploited, this vulnerability can allow an attacker to:

  1. Perform unauthorized replays of tasks by passing crafted data that circumvents nonce checks.

  2. Submit spoofed tasks that mimic valid tasks, potentially leading to unauthorized task processing and validation.

Code Snippet

function assertValidNonce(uint256 taskId, TaskRequest storage task, uint256 nonce) internal view {
bytes memory message = abi.encodePacked(taskId, task.input, task.requester, msg.sender, nonce); // @audit using abi.encodePacked with dynamic types
if (uint256(keccak256(message)) > type(uint256).max >> uint256(task.parameters.difficulty)) {
revert InvalidNonce(taskId, nonce);
}
}

Recommendation

Replace abi.encodePacked with abi.encode to avoid the risk of hash collisions. The abi.encode function adds length prefixes to dynamic types, ensuring that different inputs do not produce the same hash. This change provides a more robust and collision-resistant approach to encoding.

Revised code:

bytes memory message = abi.encode(taskId, task.input, task.requester, msg.sender, nonce);

This modification will prevent hash collisions by structuring the data correctly, thereby preserving the integrity of nonce verification and mitigating the risk of replay and spoofing attacks.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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