President Elector

First Flight #24
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

Replay Attack in rankCandidates

Summary

The rankCandidates function in the RankedChoice contract allows a voter to submit the same vote multiple times without restriction. This leads to a replay attack vulnerability, where a malicious voter can submit duplicate votes to influence the outcome of the election.

Vulnerability Details

Issue:

In the current implementation, there is no mechanism to track or prevent a voter from submitting the same ranking of candidates multiple times during a voting session. The lack of validation allows a single voter to submit their ranking repeatedly, effectively bypassing the voting restrictions.

Proof of Concept:

  1. The attacker first votes for their preferred candidates by calling the rankCandidates function.

  2. After the vote is recorded, the attacker simply calls the same rankCandidates function again with the same candidate ranking.

  3. Since there is no mechanism to prevent this, the contract records the vote a second time, allowing the attacker to effectively vote multiple times in the same session.

Add the following test to RankedChoiceTest.t.sol, it should pass due to no duplicate checks.

function testReplayAttackByVotingTwice() public {
orderedCandidates = [candidates[0], candidates[1], candidates[2]];
vm.prank(voters\[1]);
rankedChoice.rankCandidates(orderedCandidates);
vm.stopPrank();
address\[] memory firstVote = rankedChoice.getUserCurrentVote(voters\[1]);
assertEq(firstVote, orderedCandidates, "First vote was not correctly recorded");
vm.prank(voters\[1]);
rankedChoice.rankCandidates(orderedCandidates); // Replay the vote
vm.stopPrank();
address\[] memory secondVote = rankedChoice.getUserCurrentVote(voters\[1]);
assertEq(secondVote, orderedCandidates, "Second vote should not have been recorded twice");

Impact

The replay attack enables a malicious voter to vote multiple times within a single voting session, leading to an unfair advantage and compromising the integrity of the election process. The lack of tracking or nonce protection in the contract allows repeated submissions of the same vote, resulting in potential manipulation of election results.

Tools Used

Foundry: Used to run unit tests and simulate the replay attack by voting twice with the same voter.

Recommendations

To mitigate this vulnerability, implement a check in the _rankCandidates function to ensure that a voter cannot submit their vote more than once in the same voting session. This can be done by tracking whether a voter has already cast their vote and reverting if a duplicate vote is detected.

Recommended Fix:

function _rankCandidates(
address[] memory orderedCandidates,
address voter
) internal {
// Checks
if (orderedCandidates.length > MAX_CANDIDATES) {
revert RankedChoice__InvalidInput();
}
if (!_isInArray(VOTERS, voter)) {
revert RankedChoice__InvalidVoter();
}
// Add a new check to ensure the voter hasn't already voted in this session
if (s_rankings[voter][s_voteNumber].length > 0) {
revert RankedChoice__VoterHasAlreadyVoted();
}
// Internal Effects
s_rankings[voter][s_voteNumber] = orderedCandidates;
}

This mitigation will prevent voters from submitting multiple votes in the same voting session, thus protecting the system against replay attacks.

Updates

Lead Judging Commences

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Replay Attack - The same signature can be used over and over

Support

FAQs

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