Saya telah menghabiskan waktu berjam-jam untuk men-debug eksploitasi kontrak, dan biarkan saya memberi tahu Anda - serangan reentrancy adalah pembunuh diam dari smart contract. Mereka tampaknya sederhana namun sangat efektif. Mari kita selami apa itu dan bagaimana cara menghentikannya sebelum mereka menguras dana Anda.
Ketika saya pertama kali menemui kerentanan reentrancy, saya kehilangan berjam-jam tidur mencoba memahami bagaimana seseorang bisa mengeksploitasi potongan kode yang tampaknya tidak berbahaya. Konsepnya sangat sederhana dan menyebalkan: satu kontrak dapat memanggil kembali ke kontrak lain sebelum eksekusi pertama selesai.
Bayangkan ini: ContractA memiliki 10 ETH dan ContractB telah menyetor 1 ETH ke dalamnya. Ketika ContractB menarik dananya, ContractA mengirim ETH sebelum memperbarui saldo B menjadi nol. Kesalahan urutan kecil ini menciptakan celah keamanan yang besar.
Apa yang terjadi? Fungsi fallback dari kontrak jahat segera memanggil withdraw() lagi, dan karena saldo belum diperbarui, ia melewati pemeriksaan saldo lagi! Siklus ini terulang sampai ContractA benar-benar terkuras. Sangat pintar, bukan?
Berikut cara penyerang memanfaatkan ini dalam kode:
// Kontrak serangan memanggil withdraw()
// ContractA mengirim ETH yang memicu fallback()
// fallback() memanggil withdraw() lagi sebelum saldo diperbarui
// Bilas dan ulangi sampai semua dana dicuri
Saya telah melihat proyek kehilangan jutaan karena mereka tidak memahami vektor serangan sederhana ini. Ini membuat saya marah betapa banyak pengembang yang masih melakukan kesalahan pemula ini.
Tiga Teknik untuk Melindungi Kontrak Anda
Modifier nonReentrant
Ini mengunci kontrak selama eksekusi, mencegah fungsi apa pun yang ditandai dengan modifier ini untuk diakses kembali. Sederhana namun efektif.
// AMAN
require(balance > 0);
saldo = 0; // Perbarui status SEBELUM interaksi eksternal
kirim(ether);
Selalu perbarui status Anda sebelum mengirim ETH atau token!
GlobalReentrancyGuard
Untuk proyek dengan beberapa kontrak yang saling berinteraksi, ini memberikan perlindungan di seluruh ekosistem kontrak Anda dengan menggunakan mekanisme penguncian bersama.
Teknik-teknik ini bukan hanya akademis - mereka telah menyelamatkan banyak proyek dari kehancuran finansial total.
Terlalu banyak pengembang masih berpikir "itu tidak akan terjadi pada saya" dan melewatkan perlindungan ini. Jangan jadi orang itu. Setiap fungsi yang mengirim ETH atau token harus menerapkan setidaknya salah satu dari mekanisme perlindungan ini.
Ingat, dalam pengembangan smart contract, paranoia adalah fitur, bukan bug. Satu perlindungan yang terlewat bisa menghabiskan segalanya.
Halaman ini mungkin berisi konten pihak ketiga, yang disediakan untuk tujuan informasi saja (bukan pernyataan/jaminan) dan tidak boleh dianggap sebagai dukungan terhadap pandangannya oleh Gate, atau sebagai nasihat keuangan atau profesional. Lihat Penafian untuk detailnya.
Serangan Reentrancy: Memahami dan Mencegah Kerentanan Smart Contract Ini
Saya telah menghabiskan waktu berjam-jam untuk men-debug eksploitasi kontrak, dan biarkan saya memberi tahu Anda - serangan reentrancy adalah pembunuh diam dari smart contract. Mereka tampaknya sederhana namun sangat efektif. Mari kita selami apa itu dan bagaimana cara menghentikannya sebelum mereka menguras dana Anda.
Ketika saya pertama kali menemui kerentanan reentrancy, saya kehilangan berjam-jam tidur mencoba memahami bagaimana seseorang bisa mengeksploitasi potongan kode yang tampaknya tidak berbahaya. Konsepnya sangat sederhana dan menyebalkan: satu kontrak dapat memanggil kembali ke kontrak lain sebelum eksekusi pertama selesai.
Bayangkan ini: ContractA memiliki 10 ETH dan ContractB telah menyetor 1 ETH ke dalamnya. Ketika ContractB menarik dananya, ContractA mengirim ETH sebelum memperbarui saldo B menjadi nol. Kesalahan urutan kecil ini menciptakan celah keamanan yang besar.
Apa yang terjadi? Fungsi fallback dari kontrak jahat segera memanggil withdraw() lagi, dan karena saldo belum diperbarui, ia melewati pemeriksaan saldo lagi! Siklus ini terulang sampai ContractA benar-benar terkuras. Sangat pintar, bukan?
Berikut cara penyerang memanfaatkan ini dalam kode:
// Kontrak serangan memanggil withdraw() // ContractA mengirim ETH yang memicu fallback() // fallback() memanggil withdraw() lagi sebelum saldo diperbarui // Bilas dan ulangi sampai semua dana dicuri
Saya telah melihat proyek kehilangan jutaan karena mereka tidak memahami vektor serangan sederhana ini. Ini membuat saya marah betapa banyak pengembang yang masih melakukan kesalahan pemula ini.
Tiga Teknik untuk Melindungi Kontrak Anda
Modifier nonReentrant
Ini mengunci kontrak selama eksekusi, mencegah fungsi apa pun yang ditandai dengan modifier ini untuk diakses kembali. Sederhana namun efektif.
Polanya Cek-Dampak-Interaksi
Ini adalah favorit pribadi saya. Alih-alih:
// RENTAN require(balance > 0); kirim(ether); saldo = 0;
Lakukan ini:
// AMAN require(balance > 0); saldo = 0; // Perbarui status SEBELUM interaksi eksternal kirim(ether);
Selalu perbarui status Anda sebelum mengirim ETH atau token!
GlobalReentrancyGuard
Untuk proyek dengan beberapa kontrak yang saling berinteraksi, ini memberikan perlindungan di seluruh ekosistem kontrak Anda dengan menggunakan mekanisme penguncian bersama.
Teknik-teknik ini bukan hanya akademis - mereka telah menyelamatkan banyak proyek dari kehancuran finansial total.
Terlalu banyak pengembang masih berpikir "itu tidak akan terjadi pada saya" dan melewatkan perlindungan ini. Jangan jadi orang itu. Setiap fungsi yang mengirim ETH atau token harus menerapkan setidaknya salah satu dari mekanisme perlindungan ini.
Ingat, dalam pengembangan smart contract, paranoia adalah fitur, bukan bug. Satu perlindungan yang terlewat bisa menghabiskan segalanya.