安全审计-private带来的危害

ethernaut上有道题叫Vault,要求获取到密码来解锁。先看代码

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;
        }
    }
}


乍一看,感觉逻辑和计算都没有问题。按照一般说法,这个密码设置为私有是没有任何问题的。那怎么解锁呢?暴利攻击肯定是行不通,逻辑上也没有漏洞。bytes32是可以用==来判断相等,也没有问题。那会不会数据的可见性的问题。我们来看看private的官方解释:

Making something private or internal only prevents other contracts from reading or modifying the information, but it will still be visible to the whole world outside of the blockchain.


这下就明白了,private只是针对外部合约和派生合约的不可见,但是在整个区块链世界中是可以看到的,所以我们就可以使用一些办法查看到这个password值。

  • 使用web3.js或者ethers.js的方法可以获取到password的存储槽上的值,比如:

    await web3.eth.getStorageAt('合约地址', 1);

  • 可以通过区块链浏览器查看(在sepolia等测试网上无法查看)

    OK,只要获取到密码,执行unlock方法就可以开锁了,hoho