Analise smart-contract
27.03.2024

Trappole nascoste in Honeypot

I contratti intelligenti Honeypot sono un tipo di contratti intelligenti fraudolenti che sembrano attraenti per gli utenti e promettono vantaggi finanziari. Tuttavia, tali contratti contengono trappole nascoste o codice maligno, causando agli utenti la perdita dei loro fondi. al contrario.

Per proteggersi dai contratti intelligenti Honeypot è necessario ricercare e verificare a fondo il codice del contratto prima di ricerca e verificare il codice del contratto prima di utilizzarlo. Il mondo dei contratti intelligenti e della blockchain è in continua evoluzione, con nuove vulnerabilità e metodi di inganno che compaiono regolarmente, per cui è è fondamentale per gli sviluppatori, i revisori e gli utenti tenersi aggiornati sulle ultime tendenze e sugli sviluppi in questo settore. tendenze e gli sviluppi in questo settore.

Esistono molti esempi di smart contract Honeypot. In questo articolo esamineremo alcuni di questi esempi.

1. Funzione di fallback honeypot

In questo tipo di honeypot, il contratto è dotato di una funzione di "rollback" vulnerabile che apparentemente permette a chiunque di possedere il contratto e di rimuoverne il saldo. Tuttavia, tale funzione contiene una condizione nascosta che ne impedisce l'esecuzione. esecuzione.

Codice di esempio:


pragma solidity 0.4.18

contract FallbackHoneypot {
    address public owner;

    function() public payable {
        if (owner == 0) {
            owner = msg.sender;
        } else {
            revert();
        }
    }

    function withdraw() public {
        require(msg.sender == owner);
        msg.sender.transfer(this.balance);
    }
}

In this example, the fallback function allows any user to become the owner. However, the revert() operator ensures that the ownership change never happens, leaving the attacker's funds trapped in the contract.

2. Hidden condition honeypot

Such contracts contain a hidden condition or requirement that must be met for the seemingly vulnerable function to succeed. Users may think they can use the contract, but the hidden condition ensures that they cannot.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenConditionHoneypot {
    uint256 public counter = 0;

    function deposit() public payable {
        require(msg.value == 1 ether);
        counter++;
    }

    function withdraw() public {
        require(counter > 100);
        msg.sender.transfer(this.balance);
    }
}

In questo contratto, l'utente può depositare 1 etere, e sembrerebbe che dopo 100 depositi, l'utente può ritirare l'intero saldo del contratto. Tuttavia, la condizione contatore > 100 assicura che il prelievo sia possibile solo dopo 101 depositi, il che ritarda i fondi nel contratto. depositi, il che ritarda i fondi nel contratto.

3. Honeypot di rientranza

In questo tipo di honeypot, il contratto è vulnerabile a un attacco di reentrancy, in cui un aggressore può invocare ripetutamente una funzione del contratto durante il prelievo. Tuttavia, il contratto contiene un meccanismo nascosto che ne impedisce lo sfruttamento. sfruttamento.

Codice di esempio:


pragma solidity 0.4.18

contract ReentrancyHoneypot {
    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint256 _amount) public {
        require(balances[msg.sender] >= _amount);
        if (msg.sender.call.value(_amount)()) {
            balances[msg.sender] -= _amount;
        }
    }
}

In questo esempio, il contratto è vulnerabile all'attacco di rientranza a causa dell'uso di msg.sender.call.value(_amount)((). dell'uso di msg.sender.call.value(_amount)(). Tuttavia, il contratto non non consente agli utenti di depositare più del saldo iniziale, ritardando di fatto i loro i loro fondi.

reentrancy honeypot

4. Honeypot del limite del gas

In questo tipo di honeypot, il contratto sembra consentire all'utente di prelevare fondi. fondi, ma la quantità di gas necessaria per eseguire la funzione di prelievo supera il limite del blocco di gas, rendendo impossibile la transazione. supera il limite del blocco di gas, rendendo impossibile la transazione.

Codice di esempio:


pragma solidity 0.4.18

contract GasLimitHoneypot {
    uint256 constant public numArrayElements = 1000;
    uint256[numArrayElements] public someArray;

    function deposit() public payable {
        for (uint256 i = 0; i < numArrayElements; i++) {
            someArray[i] = 0;
        }
    }

    function withdraw() public {
        uint256 balance = address(this).balance;
        for (uint256 i = 0; i < numArrayElements; i++) {
            someArray[i] = 1;
        }
        msg.sender.transfer(balance);
    }
}

In questo esempio, la funzione di deposito inizializza un array con 1000 elementi. La funzione di prelievo trasferisce il saldo del contratto al mittente, ma modifica gli elementi dell'array. modifica gli elementi dell'array. Il gas richiesto per l'esecuzione del ciclo supera il limite del blocco di gas. limite del blocco di gas, il che impedisce il prelievo e lo ritarda nel contratto.

5. Honeypot di manipolazione del timestamp

In questo tipo di honeypot, il contratto utilizza il timestamp della blockchain di Ethereum come condizione di esecuzione. come condizione per l'esecuzione. Tuttavia, dal momento che i minatori possono manipolare il timestamp del blocco timestamp del blocco, il contratto diventa vulnerabile.

Codice di esempio:


pragma solidity 0.4.18

contract TimestampHoneypot {
    uint256 public lastInteraction;
    uint256 public prize;

    function deposit() public payable {
        lastInteraction = now;
        prize += msg.value;
    }

    function withdraw() public {
        require(now >= lastInteraction + 1 hours);
        msg.sender.transfer(prize);
        prize = 0;
    }
}

In questo contratto, gli utenti possono depositare fondi e ritirare l'intero saldo del contratto contratto dopo 1 ora dall'ultima interazione. Tuttavia, poiché i minatori possono manipolare il timestamp del blocco, possono attivare la funzione di ritiro prima del previsto e quindi rubare effettivamente i fondi.

6. Honeypot di trasferimento nascosto

In questo tipo di honeypot, il contratto contiene un trasferimento nascosto di fondi all'indirizzo dell'attaccante. all'indirizzo dell'aggressore, che dà l'impressione di un contratto legittimo, ma in realtà ma che in realtà si traduce in una perdita di fondi.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenTransferHoneypot {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function deposit() public payable {
        if (msg.value >= 1 ether) {
            owner.transfer(msg.value);
        }
    }

    function withdraw() public {
        require(msg.sender == owner);
        owner.transfer(address(this).balance);
    }
}

In questo esempio, il contratto sembra consentire depositi e prelievi. Tuttavia, la funzione di deposito contiene un trasferimento nascosto di fondi al proprietario (attaccante) se l'importo del deposito è uguale o superiore a 1 etere. (attaccante) se l'importo del deposito è pari o superiore a 1 etere. Gli utenti ignari che depositano fondi perderanno i loro ether, che verranno trasferiti all'indirizzo dell'aggressore. trasferiti all'indirizzo dell'aggressore.

7. Honeypot di rientranza

L'honeypot di rientranza si basa sullo sfruttamento della vulnerabilità di rientranza dei contratti. contratto, in cui una funzione del contratto può essere chiamata in modo ricorsivo prima che il suo stato venga aggiornato.

Codice di esempio:


pragma solidity 0.4.18

contract ReentrancyHoneypot {
    mapping(address => uint256) public balances;

    function deposit() public payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() public {
        uint256 amount = balances[msg.sender];
        (bool success,) = msg.sender.call.value(amount)("");
        require(success, "Withdrawal failed.");
        balances[msg.sender] = 0;
    }
}

In questo esempio, il contratto autorizza depositi e prelievi. Tuttavia, è è vulnerabile agli attacchi di rientranza. Un aggressore potrebbe creare un contratto contratto che chiama ricorsivamente la funzione di prelievo prima che il saldo venga zero, esaurendo l'intero saldo del contratto.

8. Honeypot di type casting e overflow

In questo tipo di honeypot, l'aggressore utilizza la conversione di tipo e gli integer overflow per ingannare gli utenti e far loro credere che il contratto sia sicuro, ma in realtà contiene trappole in realtà contiene trappole nascoste.

Codice di esempio:


pragma solidity 0.4.18

contract TypeCastingHoneypot {
    uint8 public count = 0;
    uint256 public reward = 1 ether;

    function increment() public payable {
        require(msg.value >= reward);

        uint8 prevCount = count;
        count++;

        if (count < prevCount) {
            msg.sender.transfer(address(this).balance);
        }
    }
}

In questo esempio, il contratto premia gli utenti che incrementano la variabile del conteggio quando inviano un importo pari o superiore all'importo della ricompensa. Tuttavia, a causa dell'uso di uint8 per la variabile del conteggio, si verifica un overflow del numero intero quando il valore raggiunge 255. Dopo l'overflow, il conteggio viene resettato a 0 e un utente malintenzionato può ottenere l'intero saldo un attaccante può ottenere l'intero saldo del contratto.

overflow honeypot

9. Delegatecall honeypot

In this type of honeypot, the attacker uses the delegatecall function to execute malicious code on behalf of a seemingly secure contract.

Codice di esempio:


pragma solidity 0.4.18

contract DelegateCallHoneypot {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function() external payable {}

    function withdraw() public {
        require(msg.sender == owner);
        owner.transfer(address(this).balance);
    }

    function execute(address _target, bytes memory _data) public {
        require(msg.sender == owner);
        (bool success,) = _target.delegatecall(_data);
        require(success, "Execution failed.");
    }
}

In questo esempio, il contratto consente depositi, prelievi e l'esecuzione di codice attraverso la funzione execute. Tuttavia, un utente malintenzionato può creare codice maligno che può manipolare lo stato del contratto, compresa la variabile owner, eseguendo la funzione delegatecall. Modificando il proprietario, un utente malintenzionato può un attaccante può ottenere il controllo del contratto e svuotare il suo bilancio.

10. Honeypot di manipolazione dello storage nascosto

In questo tipo di honeypot, l'aggressore manipola in modo nascosto le variabili di storage per indurre gli utenti a prendere il controllo del contratto.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenStorageManipulation {
    mapping(address => uint256) public balances;
    uint256 public totalSupply;
    address public owner;

    constructor() public {
        owner = msg.sender;
        balances[owner] = 1000;
        totalSupply = 1000;
    }

    function transfer(address _to, uint256 _value) public {
        require(balances[msg.sender] >= _value);
        balances[msg.sender] -= _value;
        balances[_to] += _value;

        if (totalSupply - balances[owner] >= 1000) {
            owner = _to;
        }
    }
}

In questo esempio, il contratto si presenta come un semplice contratto a gettoni. Gli utenti possono passare token l'uno all'altro e il proprietario è inizialmente impostato come creatore del contratto. contratto. Tuttavia, un attaccante può manipolare di nascosto le variabili totalSupply e per riprendere il controllo del contratto. Quando la differenza tra totalSupply e balances[owner] raggiunge 1000, la variabile owner viene aggiornata, consentendo all'aggressore di riprendere il controllo del contratto. aggiornata, consentendo all'aggressore di riprendere il controllo del contratto.

11. Nome della funzione collisione honeypot

In questo tipo di honeypot, l'aggressore utilizza le collisioni dei nomi delle funzioni per ingannare gli utenti a chiamare la funzione sbagliata.

Codice di esempio:


pragma solidity 0.4.18

contract FunctionNameCollision {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function withdraw() external {
        require(msg.sender == owner);
        msg.sender.transfer(address(this).balance);
    }

    function withdraw(uint256 amount) external {
        require(msg.sender == owner);
        owner.transfer(amount);
    }

    function() external payable {}
}

In questo esempio, il contratto ha due funzioni di ritiro. Una di esse consente al di ritirare l'intero saldo e l'altra di ritirare un determinato importo. prelevare un determinato importo. Tuttavia, se l'utente tenta di prelevare un determinato importo chiamando importo chiamando withdraw(uint256), a causa di una collisione tra i nomi delle funzioni, l'utente chiamerà inavvertitamente withdraw( uint256). l'utente chiamerà inavvertitamente withdraw() senza argomenti, con il risultato di prelevare l'intero saldo del contratto. l'intero saldo del contratto.

12. Honeypot di vulnerabilità delle delegazioni

In questo tipo di honeypot, l'attaccante utilizza delegatecall per eseguire una funzione dannosa in un altro contratto. funzione dannosa in un altro contratto, che può portare al furto di fondi dagli utenti.

Codice di esempio:


pragma solidity 0.4.18

contract DelegatecallVulnerability {
    address public owner;

    constructor() public {
        owner = msg.sender;
    }

    function withdraw() external {
        require(msg.sender == owner);
        msg.sender.transfer(address(this).balance);
    }

    function () external payable {
        if (msg.value > 1 ether) {
            this.delegatecall(msg.data);
        }
    }
}

contract Malicious {
    function withdraw() external {
        msg.sender.transfer(address(this).balance);
    }
}                

In questo esempio, il contratto sembra innocuo, con una semplice funzione withdraw() che consente al proprietario di ritirare il saldo del contratto. Tuttavia, il contratto contiene anche una funzione di fallback che, quando riceve più di 1 etere, esegue una chiamata delegata a un altro contratto utilizzando msg.data. Se un aggressore crea un contratto dannoso con withdraw() che ruba il saldo del contratto e invia più di 1 ether. contratto e invia più di 1 etere al contratto vittima, la delegatecall eseguirà il contratto delegatecall eseguirà la funzione maligna withdraw(), rubando il saldo del contratto. saldo del contratto.

vulnerability honeypot

13. Honeypot di overflow di pseudo-integri

Questo tipo di honeypot si basa sul fatto che Solidity non ha il supporto supporto integrato per i numeri in virgola mobile. Gli aggressori possono creare contratti che esteriormente utilizzano numeri decimali, ma in realtà manipolano numeri interi in modo fraudolento.

Codice di esempio:


pragma solidity 0.4.18

contract PseudoIntegersOverflow {
    mapping(address => uint256) public balances;

    function deposit() external payable {
        require(msg.value > 0);
        uint256 pseudoValue = msg.value * 100;
        balances[msg.sender] += pseudoValue;
    }

    function withdraw(uint256 amount) external {
        uint256 pseudoAmount = amount * 100;
        require(balances[msg.sender] >= pseudoAmount);
        balances[msg.sender] -= pseudoAmount;
        msg.sender.transfer(amount);
    }
}

Questo esempio dà l'impressione che il contratto gestisca il saldo dell'utente con precisione decimale, moltiplicando i valori per 100 prima di salvarli. Tuttavia, questo approccio è fuorviante, poiché Solidity non supporta i numeri in virgola mobile. Quando l'utente tenta di prelevare i suoi fondi, il contratto contratto calcola in modo errato la pseudo-somma a causa del troncamento dei numeri interi e l'utente potrebbe non essere in grado di prelevare l'utente potrebbe non essere in grado di prelevare l'intero saldo.

Per proteggersi da questo tipo di honeypot, è necessario comprendere le limiti del linguaggio Solidity e di come gestisce le operazioni numeriche. Fate attenzione quando si lavora con contratti che dichiarano di supportare la precisione decimale, e controllate sempre il codice del contratto per individuare potenziali problemi.

14. Costi nascosti nei contratti intelligenti

Alcuni contratti intelligenti dannosi possono imporre pagamenti nascosti agli utenti a loro insaputa. loro conoscenza. Tali pagamenti possono essere mascherati nel codice del contratto o essere attivati solo in determinate condizioni.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenFees {
    address public owner;
    uint256 public feePercentage;

    constructor(uint256 _feePercentage) public {
        owner = msg.sender;
        feePercentage = _feePercentage;
    }

    function withdraw(uint256 amount) external {
        uint256 fee = amount * feePercentage / 100;
        uint256 netAmount = amount - fee;
        require(address(this).balance >= netAmount);
        msg.sender.transfer(netAmount);
        owner.transfer(fee);
    }
}

In questo esempio, il creatore del contratto imposta una tariffa (feePercentage) quando distribuzione del contratto. Quando si interagisce con il contratto, gli utenti possono non essere di questa commissione. Quando un utente preleva i propri fondi, il contratto calcola la commissione il contratto calcola la commissione, la sottrae dall'importo del prelievo e invia il resto all'utente. all'utente. La commissione viene quindi trasferita al proprietario del contratto.

Per evitare di cadere in questa trappola, è necessario esaminare attentamente il codice del contratto e assicurarsi di aver compreso tutte le assicurarsi di aver compreso tutte le commissioni associate. Cercate di individuare gli accordi nascosti o mascherati. nascosti o mascherati.

15. Manipolazione nascosta dello Stato

In alcuni casi, i contratti dannosi possono consentire al proprietario del contratto o a un aggressore di manipolare lo stato interno del contratto. di manipolare lo stato interno del contratto, portando a conseguenze inaspettate per gli altri utenti. conseguenze inaspettate per gli altri utenti.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenStateManipulation {
    address public owner;
    mapping(address => uint256) public balances;

    constructor() public {
        owner = msg.sender;
    }

    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint256 amount) external {
        require(balances[msg.sender] >= amount);
        msg.sender.transfer(amount);
        balances[msg.sender] -= amount;
    }

    function manipulateBalance(address user, uint256 newBalance) external {
        require(msg.sender == owner);
        balances[user] = newBalance;
    }
}

In questo esempio, il contratto consente agli utenti di depositare e prelevare fondi. Tuttavia, la funzione manipulateBalance permette al proprietario del contratto di modificare arbitrariamente il saldo di qualsiasi utente. Questo può causare perdite inaspettate perdite inaspettate per gli utenti o consentire al proprietario del contratto di rubare fondi.

Il codice del contratto deve essere esaminato per verificare la presenza di funzioni che consentano la manipolazione dello stato, soprattutto se solo il proprietario del contratto o alcuni indirizzi manipolazione dello stato, soprattutto se solo il proprietario del contratto o determinati indirizzi hanno accesso ad essi.

hidden state manipulation

16. Furto di token nascosti

In alcuni casi, i contratti dannosi possono contenere caratteristiche nascoste che permettono al proprietario del contratto o all'attaccante di proprietario del contratto o all'attaccante di rubare token a utenti ignari.

Codice di esempio:


pragma solidity 0.4.18

contract HiddenTokenStealing {
    address public owner;
    mapping(address => uint256) public balances;

    constructor() public {
        owner = msg.sender;
    }

    function deposit(IERC20 token, uint256 amount) external {
        require(token.transferFrom(msg.sender, address(this), amount));
        balances[msg.sender] += amount;
    }

    function withdraw(IERC20 token, uint256 amount) external {
        require(balances[msg.sender] >= amount);
        require(token.transfer(msg.sender, amount));
        balances[msg.sender] -= amount;
    }

    function stealTokens(IERC20 token, address user, uint256 amount) external {
        require(msg.sender == owner);
        require(token.transfer(owner, amount));
        balances[user] -= amount;
    }
}

In questo esempio, il contratto consente agli utenti di depositare e prelevare gettoni ERC20 token. Tuttavia, la funzione rubaTokens permette al proprietario del contratto di rubare token da qualsiasi utente.

Conclusione:

Honeypot è solo uno dei tanti schemi fraudolenti della DeFi che utilizza non solo la non solo la limitazione dei prelievi, ma anche le varie trappole nascoste descritte in precedenza. sopra.

Per non cadere nell'esca, è necessario comprendere le peculiarità dello schema fraudolento, le schema fraudolento, le sottigliezze del linguaggio di programmazione Solidity e studiare a fondo gli smart contract prima di interagire con essi. studiare a fondo i contratti intelligenti prima di interagire con essi.

Rimanendo informati e conducendo un'accurata due diligence, è possibile ridurre al minimo i rischi associati all'uso degli smart i rischi associati all'uso dei contratti intelligenti.

 

Se avete dubbi sulla sicurezza o sulla funzionalità di un contratto smart utilizzate la nostra piattaforma Lotus Market.

 

 

La piattaforma Lotus Market è stata creata da un team di sviluppatori esperti e di revisori professionisti. L'obiettivo del progetto è quello di ridurre al minimo i rischi di di investire in token fraudolenti e aiutare a commerciare criptovalute in modo sicuro e comodamente.

 

Saluti, team Lotus Market.

All posts

Connect to a wallet

Metamask