Link Search Menu Expand Document

Sensitive Information Disclosure in Smart Contracts

Play SecureFlag Play Smart Contracts Labs on this vulnerability with SecureFlag!

Smart contracts, such as those used to govern games and auctions, typically need to receive and store secret data. This aspect must be taken into account when developing smart contracts since, given the public nature of the blockchain, any sensitive data from the contract can be read and potentially exploited.

This lack of confidentiality opens the door to a range of attacks that can compromise the integrity and availability of the smart contract and can even lead to unauthorized withdrawals.

Insecure Secrets Storage

Data stored in the blockchain is always readable, despite their variable types. It’s important to keep private data off-chain or carefully encrypt it.

Vulnerable example

This vulnerable contract releases the full balance to any user that submits the same password passed in the constructor at the time the contract was initially deployed.

contract ProtectedSafe {
    string private password;
    
    constructor(string _password) {
        password = _password;
    }

    function release(string _password) public {
        require (password == _password, "Error, wrong password!");
        selfdestruct(msg.sender);
    }
}

The contract can be compromised by disclosing the variable password, which is readable by anyone who accesses the storage belonging to the contract instance, e.g., by calling web3.eth.getStorageAt() in the Ethereum client.

Fixed example

The vulnerability can be remediated by saving the hashed version of the password.

contract ProtectedSafe {
    string private hashedPassword;
    
    constructor(string _hashedPassword) {
        hashedPassword = _hashedPassword;
    }

    function release(string _password) public {
        require (password == sha256(_password), "Error, wrong password!");
        selfdestruct(msg.sender);
    }
}

Observe that the code above remediates the Insecure Secrets Storage vulnerability; however, it still suffers from a Front-Running attack.

Prevention

There is no such thing as secret data in a contract or transaction; internal and private variables can be disclosed by anyone.

Encryption in Solidity suffers from heavy limitations; however, the below points describe current agreed best practices to mitigate risk:

  • Encrypt data before sending it to the contract, or it will be visible in the transaction that was initially used to send the data to the contract.
  • Key management APIs are not supported by Solidity, and private keys can’t be stored or passed to the contract due to the reason above.
  • Asymmetric encryption APIs are not supported by Solidity.

Hashing should be used with caution:

  • Hash data before sending it to the contract, or it will be visible in the transaction that was initially used to send the data to the contract.
  • Solidity supports a limited number of hash functions: Keccak256 (SHA-3 by Ethereum), SHA256, RIPEMD-160.

Front-Running attacks

Data transmitted in the blockchain is always readable, and this complete transparency allows any actor running an Ethereum node to read transactions before they are finalized. This opens the door to race condition attacks against contract functions that depend on the order of the transactions submitted to it.

The simplest example of a race condition is when a smart contract gives a reward for submitting information. In a scenario such as this, a malicious actor could try to submit the correct answer prior to the legitimate winner’s public transaction being processed to win the race condition and win the game.

Prevention

Preventative measures against Front-Running attacks make use of a commitment scheme strategy called commit reveal hash scheme.

With this secure programming pattern, the parties submit a hashed answer in the form of hash(salt, address, answer) that is stored by the contract with the sender’s address. Then, to later claim the reward, the sender submits a second transaction with the salt and answer in order for them to be hashed by the receiving contract to check the first transaction’s validity.

References

Consensys - Ethereum Smart Contract Best Practices - Frontrunning Solidity - Mathematical and Cryptographic Functions Wikipedia - Commitment Scheme SWC Registry - Transaction Order Dependence Consensys - Smart Contract Security Best Practices