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

Missing Access Control for setPassword() that has as a consequence that anyone can set the password

Summary

The setPassword function lacks the necessary access control mechanisms, creating a vulnerability that allows anyone to call it freely and change the password.

Vulnerability Details

function setPassword(string memory newPassword) external {
s_password = newPassword;
emit SetNetPassword();
}

The setPassword function is missing an onlyOwner modifier or a similar check with getPassword() function.

function getPassword() external view returns (string memory) {
@> if (msg.sender != s_owner) {
revert PasswordStore__NotOwner();
}

And here is the Foundry PoC:

function test_non_owner_can_set_password() public {
// Set password as the owner to have it to compare later
vm.startPrank(owner);
string memory ownerPasswordSet = "newOwnerPassword";
passwordStore.setPassword(ownerPasswordSet);
string memory ownerPasswordGet = passwordStore.getPassword();
// Set password as a malicious user
vm.startPrank(address(1337));
string memory maliciousPasswordSet = "newMaliciousPassword";
passwordStore.setPassword(maliciousPasswordSet);
// Get the password after both the owner and the malicious user have set their own passwords
vm.startPrank(owner);
string memory finalPassword = passwordStore.getPassword();
// The `finalPassword` must not be the owner's password to prove the bug
assertNotEq(ownerPasswordGet, finalPassword);
// The `finalPassword` must be the malicious's password to prove the bug
assertEq(maliciousPasswordSet, finalPassword);
}

Impact

This is a critical security concern as it exposes the contract to unauthorized alterations of the stored password, jeopardizing data confidentiality and overall security.

Tools Used

  • foundry

Recommendations

There are three recommendations to be considered:

  1. Implement onlyOwner modifier.

@@ -19,11 +19,22 @@ contract PasswordStore {
s_owner = msg.sender;
}
+ // https://solidity-by-example.org/function-modifier/
+ // Modifier to check that the caller is the owner of
+ // the contract.
+ modifier onlyOwner() {
+ require(msg.sender == s_owner, "Not owner");
+ // Underscore is a special character only used inside
+ // a function modifier and it tells Solidity to
+ // execute the rest of the code.
+ _;
+ }
+
/*
* @notice This function allows only the owner to set a new password.
* @param newPassword The new password to set.
*/
- function setPassword(string memory newPassword) external {
+ function setPassword(string memory newPassword) external onlyOwner {
s_password = newPassword;
emit SetNetPassword();
}
  1. Add a similar check with revert like in getPassword().

@@ -24,6 +24,9 @@ contract PasswordStore {
* @param newPassword The new password to set.
*/
function setPassword(string memory newPassword) external {
+ if (msg.sender != s_owner) {
+ revert PasswordStore__NotOwner();
+ }
s_password = newPassword;
emit SetNetPassword();
}
  1. Add a similar check like in getPassword() but with require.

@@ -24,6 +24,9 @@ contract PasswordStore {
* @param newPassword The new password to set.
*/
function setPassword(string memory newPassword) external {
+ require(msg.sender == s_owner, "Not owner");
s_password = newPassword;
emit SetNetPassword();
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
almost 2 years ago
inallhonesty Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-lacking-access-control

Anyone can call `setPassword` and set a new password contrary to the intended purpose.

Support

FAQs

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