Ethernaut Level 12 titled “Privacy” challenges the concept of “private” data on the blockchain. In this level, you’ll encounter a locked contract, and your objective is to unlock it. The key, however, isn’t so private after all! It lies in the way the Ethereum Virtual Machine (EVM) stores data. This walkthrough will guide you through the process.
Understanding Storage Slots
Imagine a shoebox with compartments. The EVM stores variables similarly, allocating 32 bytes (256 bits) to each compartment called a storage slot. The EVM is space-efficient; smaller variables like booleans (1 byte) or uint8s (1 byte) can share a slot with other variables as long as the total size doesn’t exceed 32 bytes. This level serves as a valuable lesson in understanding how the EVM stores data.
Analyze the Contract
First, take a look at the Privacy.sol
contract. You’ll notice a variable named data
declared as a bytes32
array. There’s also a function called unlock
that takes a bytes16
argument as input.
EVM Storage Shenanigans
The EVM packs variables efficiently to save storage space. Smaller variables like locked
(bool) and denomination
(uint8) share the same storage slot as the first element of the data
array (data[0]
).
Unlocking the Secret
To unlock the contract, we need the value stored in data[2]
. That value is located at slot 5. However, the EVM stores it as bytes32
. We need to cast it to bytes16
to match the unlock
function’s input.
Here’s a step-by-step guide to unlocking the contract:
- Use the terminal in the console:
- Get the Hex string of the
data[2]
at slot 5:await web3.eth.getStorageAt(contract.address, 5)
. This will give us a string ofbytes32
. We want to convert it tobytes16
. - Put that hex string in a constant:
const b32 = '0x5d6655fba48ea25651c1cad326e3a62ded205cb4464b71e0cf64951ecfe605d2'
. - Find the length:
b32.length
(This will return 66). - Convert it to
bytes16
(half the length, excluding0x
):const b16 = b32.slice(0, 34)
. - Use that value to call the
unlock
function:contract.unlock('0x5d6655fba48ea25651c1cad326e3a62d')
.
- Check the status of the
locked
boolean to see if it changed tofalse
:await contract.locked()
. - Finally, you can submit the instance. Congrats on completing this level!
Conclusion: Ethernaut level 12 (Privacy)
This challenge highlights that nothing on the blockchain is truly private, not even data declared with the private
keyword. The EVM’s storage layout can reveal information you might think is hidden. So, when building smart contracts, be mindful of how data is stored and accessed. Rely on encryption or other secure mechanisms for truly sensitive information.
Bonus Tip: Security best practices involve keeping user data off-chain whenever possible. Consider using decentralized storage solutions for sensitive information that doesn’t require constant on-chain interaction.
FAQs:
- Can this exploit be used to steal funds from real contracts?
No, directly exploiting storage packing like this wouldn’t be effective for stealing funds from real contracts. This technique relies on specific contract vulnerabilities and wouldn’t work universally.
- What are some best practices to avoid similar vulnerabilities?
When writing smart contracts, be mindful of storage slot packing. Avoid storing sensitive data directly on-chain, and consider using encryption or alternative storage solutions for truly private information.
- Is there another way to solve this challenge without the Truffle console?
Yes, it’s possible to solve this challenge using other tools or platforms that allow interaction with deployed contracts and storage slots.
- What if I don’t know the storage slot locations beforehand?
Analyzing the contract code and understanding Solidity variable sizes can help you predict storage slot usage. Alternatively, some tools offer functionalities to explore storage slots on deployed contracts.
- What are the limitations of the “private” keyword in Solidity?
The private
keyword in Solidity only affects code visibility within the contract itself. It doesn’t guarantee data privacy on the blockchain due to the EVM’s storage layout and potential for analysis.