Analise smart-contract
27.03.2024

Perangkap tersembunyi di Honeypot

Kontrak pintar Honeypot adalah salah satu jenis kontrak pintar palsu yang terlihat menarik bagi pengguna dan menjanjikan keuntungan finansial. Akan tetapi, kontrak tersebut mengandung jebakan tersembunyi atau kode berbahaya, menyebabkan pengguna kehilangan dana mereka sebaliknya.

Untuk melindungi diri Anda dari kontrak pintar Honeypot, Anda harus benar-benar meneliti dan memverifikasi kode kontrak sebelum terlibat dengannya. Dunia kontrak pintar dan blockchain terus berkembang, dengan kerentanan dan metode penipuan yang muncul secara teratur, jadi sangat penting bagi para pengembang, auditor, dan pengguna untuk selalu mengikuti perkembangan terbaru tren dan perkembangan terbaru di bidang ini.

Ada banyak contoh kontrak pintar Honeypot. Dalam artikel ini kita akan melihat beberapa contohnya.

1. Honeypot fungsi fallback

Pada jenis honeypot ini, kontrak memiliki fitur "rollback" yang rentan yang tampaknya memungkinkan siapa saja untuk memiliki kontrak dan menghapus saldonya. Akan tetapi, fitur tersebut mengandung kondisi tersembunyi yang mencegah keberhasilan eksekusi.

Contoh kode:


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

Dalam contoh ini, fungsi fallback memungkinkan setiap pengguna untuk menjadi pemilik. Akan tetapi, operator revert() memastikan bahwa perubahan kepemilikan tidak pernah terjadi, membuat dana penyerang terjebak dalam kontrak.

2. Hidden condition honeypot

Kontrak semacam itu mengandung kondisi atau persyaratan tersembunyi yang harus dipenuhi untuk fungsi yang tampaknya rentan untuk berhasil. Para pengguna mungkin berpikir bahwa mereka dapat menggunakan kontrak tersebut, tetapi kondisi tersembunyi memastikan bahwa mereka tidak bisa.

Contoh kode:


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

Dalam kontrak ini, pengguna dapat menyetor 1 eter, dan tampaknya setelah 100 setoran, pengguna dapat menarik seluruh saldo kontrak. Namun, kondisi penghitung kondisi > 100 memastikan bahwa penarikan hanya mungkin dilakukan setelah 101 setoran, yang menunda dana dalam kontrak.

3. Honeypot pendaftaran ulang

Pada jenis honeypot ini, kontrak rentan terhadap serangan masuk kembali, di mana penyerang dapat berulang kali memanggil fungsi kontrak selama penarikan. Akan tetapi, kontrak berisi mekanisme tersembunyi yang mencegah keberhasilan eksploitasi.

Contoh kode:


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

Dalam contoh ini, kontrak rentan terhadap serangan masuk kembali karena karena penggunaan msg.sender.call.value(_amount)(). Akan tetapi, kontrak tersebut tidak mengizinkan pengguna untuk menyetor lebih dari saldo awal, yang secara efektif menunda dana mereka.

reentrancy honeypot

4. Honeypot batas gas

Dalam jenis honeypot ini, kontrak tampaknya memungkinkan pengguna untuk menarik dana, tetapi jumlah gas yang diperlukan untuk melakukan fungsi penarikan melebihi batas blok gas, sehingga transaksi tidak mungkin dilakukan.

Contoh kode:


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

Pada contoh ini, fungsi deposit menginisialisasi sebuah larik dengan 1000 elemen. Fungsi penarikan mentransfer saldo kontrak ke pengirim, tetapi memodifikasi elemen larik. Gas yang dibutuhkan untuk menjalankan perulangan melebihi batas batas blok gas, yang mencegah penarikan dan menundanya dalam kontrak.

5. Honeypot manipulasi stempel waktu

Pada jenis honeypot ini, kontrak menggunakan stempel waktu blockchain Ethereum sebagai syarat untuk eksekusi. Akan tetapi, karena penambang dapat memanipulasi blok timestamp, kontrak menjadi rentan.

Contoh kode:


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

Dalam kontrak ini, pengguna dapat menyetor dana dan menarik seluruh setelah 1 jam dari interaksi terakhir. Akan tetapi, karena penambang dapat memanipulasi stempel waktu blok, mereka dapat memicu fungsi penarikan lebih awal dari yang diharapkan dan dengan demikian benar-benar mencuri dana.

6. Honeypot transfer tersembunyi

Pada jenis honeypot ini, kontrak berisi transfer dana tersembunyi ke alamat penyerang, yang memberikan tampilan kontrak yang sah tetapi pada kenyataannya mengakibatkan hilangnya dana.

Contoh kode:


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

Dalam contoh ini, kontrak tampaknya mengizinkan setoran dan penarikan. Namun, fungsi setoran berisi transfer dana tersembunyi ke pemilik (penyerang) jika jumlah setoran sama dengan atau lebih besar dari 1 eter. Pengguna yang tidak menaruh curiga yang menyetor dana akan kehilangan eter mereka, karena mereka akan ditransfer ke alamat penyerang.

7. Reentrancy honeypot

Reentrancy honeypot didasarkan pada eksploitasi kerentanan reentrancy dalam kontrak, di mana fungsi kontrak dapat dipanggil secara rekursif sebelum statusnya statusnya diperbarui.

Contoh kode:


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

Dalam contoh ini, kontrak mengesahkan deposit dan penarikan dana. Akan tetapi, ini rentan terhadap serangan masuk kembali. Seorang penyerang dapat membuat kontrak yang secara rekursif memanggil fungsi penarikan sebelum saldo disetel ke nol, menghabiskan seluruh saldo kontrak.

8. Tipe casting dan overflow honeypot

Pada jenis honeypot ini, penyerang menggunakan konversi tipe dan bilangan bulat melimpah untuk mengelabui pengguna agar percaya bahwa kontrak tersebut aman, tetapi sebenarnya sebenarnya mengandung jebakan tersembunyi.

Contoh kode:


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

Dalam contoh ini, kontrak memberikan imbalan kepada pengguna yang menambah variabel count ketika mereka mengirim jumlah yang sama atau lebih besar dari jumlah hadiah. Namun, karena penggunaan uint8 untuk variabel count, terjadi overflow bilangan bulat ketika nilainya mencapai 255. Setelah overflow, hitungan disetel ulang ke 0, dan penyerang dapat memperoleh seluruh saldo kontrak.

overflow honeypot

9. Panggilan delegasi honeypot

Pada jenis honeypot ini, penyerang menggunakan fungsi delegatecall untuk mengeksekusi kode berbahaya atas nama kontrak yang tampaknya aman.

Contoh kode:


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.");
    }
}

Dalam contoh ini, kontrak mengizinkan penyetoran, penarikan, dan eksekusi kode melalui fungsi eksekusi. Akan tetapi, penyerang dapat membuat kode berbahaya yang dapat memanipulasi keadaan kontrak, termasuk variabel pemilik, dengan menjalankan fungsi delegatecall. Dengan mengubah pemilik, penyerang dapat mendapatkan kendali atas kontrak dan mengosongkan saldonya.

10. Honeypot manipulasi penyimpanan tersembunyi

Pada jenis honeypot ini, penyerang secara diam-diam memanipulasi variabel penyimpanan untuk mengelabui pengguna agar dapat mengendalikan kontrak.

Contoh kode:


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

Dalam contoh ini, kontrak terlihat seperti kontrak token sederhana. Pengguna dapat memberikan token satu sama lain, dan pemilik pada awalnya ditetapkan sebagai pencipta kontrak. Akan tetapi, penyerang dapat secara diam-diam memanipulasi variabel totalSupply dan variabel saldo untuk mendapatkan kembali kendali atas kontrak. Ketika perbedaan antara totalSupply dan saldo [pemilik] mencapai 1000, variabel pemilik diperbarui, yang memungkinkan penyerang untuk mendapatkan kembali kendali atas kontrak.

11. Nama fungsi tabrakan honeypot

Pada jenis honeypot ini, penyerang menggunakan tabrakan nama fungsi untuk mengelabui pengguna untuk memanggil fungsi yang salah.

Contoh kode:


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

Dalam contoh ini, kontrak memiliki dua fungsi penarikan. Salah satunya memungkinkan pemilik untuk menarik seluruh saldo dan yang lainnya memungkinkan pemilik untuk menarik jumlah tertentu. Namun, jika pengguna mencoba menarik sejumlah tertentu jumlah tertentu dengan memanggil withdraw (uint256), karena tabrakan nama fungsi, maka pengguna akan secara tidak sengaja memanggil withdraw() tanpa argumen, yang akan menghasilkan dalam menarik seluruh saldo kontrak.

12. Kerentanan honeypot panggilan delegasi

Pada jenis honeypot ini, penyerang menggunakan delegatecall untuk mengeksekusi fungsi berbahaya dalam kontrak lain, yang dapat menyebabkan pencurian dana dari pengguna.

Contoh kode:


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

Dalam contoh ini, kontrak tampaknya tidak berbahaya, dengan fungsi penarikan sederhana() yang memungkinkan pemilik untuk menarik saldo kontrak. Akan tetapi, kontrak tersebut juga berisi fungsi fallback yang, ketika menerima lebih dari 1 eter, melakukan panggilan delegasi dari kontrak lain menggunakan msg.data. Jika penyerang membuat kontrak berbahaya dengan withdraw() yang mencuri saldo kontrak dan mengirim lebih dari 1 eter ke kontrak korban, maka delegatecall akan mengeksekusi fungsi withdraw() yang berbahaya, mencuri saldo kontrak.

vulnerability honeypot

13. Bilangan bulat semu melimpah melimpah

Jenis honeypot ini didasarkan pada fakta bahwa Solidity tidak memiliki dukungan bawaan untuk bilangan floating point. Penyerang dapat membuat kontrak yang secara lahiriah menggunakan bilangan desimal tetapi sebenarnya memanipulasi bilangan bulat secara curang.

Contoh kode:


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

Contoh ini memberikan kesan bahwa kontrak mengelola saldo pengguna dengan presisi desimal dengan mengalikan nilai dengan 100 sebelum menyimpannya. Akan tetapi, pendekatan ini menyesatkan karena Solidity tidak mendukung angka floating point. Ketika pengguna mencoba untuk menarik dana mereka, kontrak kontrak salah menghitung jumlah semu karena pemotongan bilangan bulat, dan pengguna mungkin tidak dapat menarik seluruh saldo mereka.

Untuk melindungi dari jenis honeypot ini, Anda perlu memahami keterbatasan bahasa Solidity dan bagaimana bahasa ini menangani operasi numerik. Berhati-hatilah Berhati-hatilah saat bekerja dengan kontrak yang mengklaim mendukung presisi desimal, dan selalu periksa kode kontrak untuk potensi masalah.

14. Biaya tersembunyi dalam smart contract

Beberapa smart contract yang berbahaya dapat membebankan pembayaran tersembunyi kepada pengguna tanpa tanpa sepengetahuan mereka. Pembayaran tersebut dapat disamarkan dalam kode kontrak atau dipicu hanya dalam kondisi tertentu.

Contoh kode:


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

Dalam contoh ini, pembuat kontrak menetapkan biaya (feePercentage) ketika saat menerapkan kontrak. Ketika berinteraksi dengan kontrak, pengguna mungkin tidak tidak menyadari biaya ini. Ketika pengguna menarik dana mereka, kontrak akan menghitung biaya, menguranginya dari jumlah penarikan, dan mengirimkan sisanya ke pengguna. Komisi kemudian ditransfer ke pemilik kontrak.

Untuk menghindari jebakan ini, tinjau kode kontrak dengan cermat dan pastikan Anda memahami semua biaya terkait. Carilah penyelesaian yang tersembunyi atau terselubung. yang tersembunyi atau terselubung.

15. Manipulasi negara yang tersembunyi

Dalam beberapa kasus, kontrak berbahaya dapat memungkinkan pemilik kontrak atau penyerang untuk memanipulasi keadaan internal kontrak, yang mengarah ke yang tidak terduga bagi pengguna lain.

Contoh kode:


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

Dalam contoh ini, kontrak mengizinkan pengguna untuk menyetor dan menarik dana. Namun, fungsi manipulateBalance memungkinkan pemilik kontrak untuk mengubah saldo pengguna mana pun secara sewenang-wenang. Hal ini dapat mengakibatkan hal yang tidak terduga kerugian yang tidak terduga bagi pengguna atau memungkinkan pemilik kontrak untuk mencuri dana.

Kode kontrak harus diteliti untuk fitur-fitur yang memungkinkan manipulasi, terutama jika hanya pemilik kontrak atau alamat tertentu yang memiliki memiliki akses ke sana.

hidden state manipulation

16. Pencurian token tersembunyi

Dalam beberapa kasus, kontrak berbahaya dapat berisi fitur tersembunyi yang memungkinkan pemilik kontrak atau penyerang untuk mencuri token dari pengguna yang tidak menaruh curiga.

Contoh kode:


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

Dalam contoh ini, kontrak memungkinkan pengguna untuk menyetor dan menarik ERC20 token. Namun, fungsi stealTokens memungkinkan pemilik kontrak untuk mencuri token dari pengguna mana pun.

Kesimpulan:

Honeypot hanyalah salah satu dari banyak skema penipuan di DeFi yang tidak memanfaatkan tidak hanya pembatasan penarikan, tetapi juga berbagai jebakan tersembunyi yang dijelaskan di atas.

Agar tidak terjebak dalam umpan, Anda perlu memahami kekhasan skema penipuan, seluk-beluk bahasa pemrograman Solidity dan mempelajari kontrak pintar secara menyeluruh sebelum berinteraksi dengannya.

Dengan tetap terinformasi dan melakukan uji tuntas secara menyeluruh, Anda dapat meminimalkan risiko yang terkait dengan penggunaan smart contract.

 

Jika Anda ragu dengan keamanan atau fungsionalitas smart contract gunakan platform Lotus Market kami.

 

 

Platform Lotus Market dibuat oleh tim pengembang berpengalaman dan auditor profesional. Tujuan dari proyek ini adalah untuk meminimalkan risiko berinvestasi dalam token palsu dan membantu memperdagangkan mata uang kripto dengan aman dan dengan aman dan nyaman.

 

Salam, tim Lotus Market.

All posts

Connect to a wallet

Metamask