For the PasswordStore
contract, the assumtion of the developer as per the NatSpec, is that only the owner can read the password. The password is set in storage with a state visibility of private
but anyone can access the variable's state by reading the contract state which is unsafe as passwords are sensitive data and negates this assumtion.
The PasswordStore
contract stores the password in a storage variable named s_password
with a state visibility of private
on line 14 of PasswordStore.sol
. A variable with a state visibility of private means that the variable can only be acessed within the contract it is defined. This means that an inheriting contract cannot modify or read the variable. However, all data on the blockchain can be read from outside the blockchain through the contract storage. This means that the position of the password in storage can be determined and then the value read from the blockchain.
Since the state visibility doesn't prevent others from accessing the variable from storage, anyone, including a malicious actor, can access the owner's password by reading the contract storage.
The password is marked as private
but the data is still able to be read from outside the blockchain.
The NatSpec states: This contract allows you to store a private password that others won't be able to see
. Since others will be able to view the password by inspecting the storage, the password is not secure and therefore vulnerable to being stolen.
The context of this contract is unknown, and hence the true impact is unknown. For example, if the contract is to be used as an on-chain password manager, securing the password to be inaccessible to others is crucial.
Since only the owner being able to read the password is the core assumtion, and functionality that does not hold, this is a high severity vulnerability.
To read the password, the contract first needs to be deployed.
Using the local testnet node anvil to deploy and inspect the contract:
Running the DeployPasswordStore.s.sol
script deploys the contract and sets the password to "myPassword"
:
Anvil logs output:
By inspecting the contract, it can be seen that the storage slot of the password variable is slot 1. For completeness, forge
is used to inspect the contract storage and to confirm this. This shows that the password is stored at storge slot 1:
Reading storage slot 1 of the contract yields the following output:
The output can then be converted to a human-readable ASCII string:
The password that was set using the script was successfully read from storage and hence, non-owners will be able to read it.
Do not store sensitive information on-chain, unless encrypted. If sensitive information is required to be stored on-chain, the data needs to be asymetrically encrypted (public-key cryptography) which allows the data to be encrypted with a private key. Only the owner of the corresponding private key can then decrypt the data. Common examples of asymmetric encryption include Rivest-Shamir-Adleman (RSA) and Elliptic Curve Cryptography (ECC).
Private functions and state variables are only visible for the contract they are defined in and not in derived contracts. In this case private doesn't mean secret/confidential
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.