Dasar
Spot
Perdagangkan kripto dengan bebas
Perdagangan Margin
Perbesar keuntungan Anda dengan leverage
Konversi & Investasi Otomatis
0 Fees
Perdagangkan dalam ukuran berapa pun tanpa biaya dan tanpa slippage
ETF
Dapatkan eksposur ke posisi leverage dengan mudah
Perdagangan Pre-Market
Perdagangkan token baru sebelum listing
Futures
Akses ribuan kontrak perpetual
TradFi
Emas
Satu platform aset tradisional global
Opsi
Hot
Perdagangkan Opsi Vanilla ala Eropa
Akun Terpadu
Memaksimalkan efisiensi modal Anda
Perdagangan Demo
Pengantar tentang Perdagangan Futures
Bersiap untuk perdagangan futures Anda
Acara Futures
Gabung acara & dapatkan hadiah
Perdagangan Demo
Gunakan dana virtual untuk merasakan perdagangan bebas risiko
Peluncuran
CandyDrop
Koleksi permen untuk mendapatkan airdrop
Launchpool
Staking cepat, dapatkan token baru yang potensial
HODLer Airdrop
Pegang GT dan dapatkan airdrop besar secara gratis
Launchpad
Jadi yang pertama untuk proyek token besar berikutnya
Poin Alpha
Perdagangkan aset on-chain, raih airdrop
Poin Futures
Dapatkan poin futures dan klaim hadiah airdrop
Investasi
Simple Earn
Dapatkan bunga dengan token yang menganggur
Investasi Otomatis
Investasi otomatis secara teratur
Investasi Ganda
Keuntungan dari volatilitas pasar
Soft Staking
Dapatkan hadiah dengan staking fleksibel
Pinjaman Kripto
0 Fees
Menjaminkan satu kripto untuk meminjam kripto lainnya
Pusat Peminjaman
Hub Peminjaman Terpadu
# Memahami Mendalam tentang Serangan Reentrancy dan Cara Pencegahan yang Efektif
## Apa itu Serangan Reentrancy?
Serangan reentrancy adalah kerentanan keamanan yang terjadi ketika fungsi smart contract dapat dipanggil kembali (re-entered) sebelum eksekusi pertamanya selesai. Penyerang memanfaatkan celah ini untuk mengekstrak dana atau memanipulasi status kontrak.
## Mekanisme Serangan
**Skenario Klasik:**
1. Penyerang memanggil fungsi `withdraw()` untuk menarik dana
2. Sebelum saldo diperbarui, kontrak mengirim ETH kepada penyerang
3. Penyerang memicu callback fallback untuk memanggil `withdraw()` lagi
4. Proses berulang, mengekstrak dana lebih banyak dari yang tersedia
## Contoh Kode Rentan
```solidity
// ❌ RENTAN TERHADAP REENTRANCY
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
balances[msg.sender] -= amount;
}
```
## Teknik Pencegahan
### 1. **Checks-Effects-Interactions (CEI)**
```solidity
// ✅ AMAN - Perbarui status sebelum transfer
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount);
balances[msg.sender] -= amount; // Effects
(bool success, ) = msg.sender.call{value: amount}(""); // Interactions
require(success);
}
```
### 2. **Mutex Lock (ReentrancyGuard)**
```solidity
// OpenZeppelin ReentrancyGuard
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract SafeWithdraw is ReentrancyGuard {
function withdraw(uint amount) public nonReentrant {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
balances[msg.sender] -= amount;
}
}
```
### 3. **Pull over Push Pattern**
```solidity
// ✅ AMAN - Pengguna menarik dana sendiri
mapping(address => uint) public pendingWithdrawals;
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
}
```
## Jenis-Jenis Reentrancy
| Tipe | Deskripsi | Ciri Khas |
|------|-----------|----------|
| **Single-function** | Fungsi memanggil dirinya kembali | Paling umum |
| **Cross-function** | Fungsi A memanggil fungsi B yang masuk kembali ke A | Lebih kompleks |
| **Cross-contract** | Serangan lintas kontrak | Sulit dideteksi |
## Best Practices Keamanan
✅ **Yang Harus Dilakukan:**
- Gunakan ReentrancyGuard untuk operasi transfer
- Terapkan pola CEI secara konsisten
- Perbarui state sebelum memanggil external calls
- Pilih pull pattern daripada push pattern
- Audit kode oleh profesional keamanan
❌ **Yang Harus Dihindari:**
- Menggunakan `transfer()` atau `send()` tanpa protection
- Memanggil external functions sebelum mengupdate storage
- Mempercayai kode eksternal tanpa verifikasi
- Menggunakan low-level calls tanpa hati-hati
## Alat Deteksi
- **Slither** - Static analysis framework
- **Mythril** - Symbolic execution tool
- **OpenZeppelin Defender** - Runtime monitoring
- **Trail of Bits** - Security audit services
Pemahaman mendalam tentang reentrancy dan penerapan teknik pencegahan yang tepat adalah kunci untuk membangun smart contract yang aman dan dapat dipercaya.
Serangan reentrancy adalah salah satu ancaman keamanan paling serius terhadap smart contract. Artikel ini akan memandu Anda tidak hanya tentang cara kerja reentrancy, tetapi juga tentang cara melindungi proyek Anda secara menyeluruh.
Agar mendapatkan gambaran lengkap, kita akan memulai dari konsep dasar, kemudian menganalisis kode sumber dari serangan nyata, dan akhirnya mengeksplorasi tiga teknik perlindungan yang terbukti efektif: mulai dari modifier nonReentrant() hingga GlobalReentrancyGuard() dan pola check-effect-interaction.
Apa itu serangan reentrancy?
Bayangkan dua smart contract berinteraksi satu sama lain. ContractA dan ContractB sepenuhnya mampu memanggil satu sama lain. Itu terlihat normal, tetapi sebenarnya itu adalah celah yang bisa dieksploitasi oleh penyerang.
Konsep inti dari reentrancy adalah: sebuah smart contract dapat memanggil balik kontrak lain saat kontrak tersebut masih dalam proses eksekusi. Ini dapat menciptakan loop tak berujung jika tidak dikendalikan dengan benar.
Sebagai ilustrasi, pertimbangkan situasi berikut: ContractA memegang 10 Ether, di mana ContractB telah mengirimkan 1 Ether ke sana. Secara normal, saat ContractB meminta penarikan, kontrak akan memeriksa (saldo > 0), menerima Ether, lalu mengatur saldo menjadi 0. Tetapi dengan reentrancy, proses ini bisa diulang berkali-kali sebelum langkah pembaruan saldo dilakukan.
Mekanisme kerja serangan reentrancy
Penyerang membutuhkan dua komponen utama: sebuah fungsi attack() dan sebuah fungsi fallback().
Fungsi fallback adalah fungsi khusus dalam Solidity—fungsi luar yang tidak memiliki nama, tidak memiliki parameter, dan tidak mengembalikan nilai. Fungsi ini otomatis diaktifkan ketika:
Sekarang, ikuti langkah-langkah bagaimana serangan ini berlangsung:
Langkah 1: Penyerang memanggil fungsi attack(), di dalamnya memanggil fungsi penarikan dari ContractA.
Langkah 2: ContractA memeriksa apakah saldo ContractB lebih dari 0. Karena benar demikian, kontrak mengirim 1 Ether ke ContractB dan mengaktifkan fungsi fallback.
Langkah 3: Pada titik ini, yang penting—saldo belum diperbarui menjadi 0. ContractA masih menjalankan kode fungsi penarikan.
Langkah 4: Fungsi fallback diaktifkan dan langsung memanggil kembali fungsi penarikan dari ContractA.
Langkah 5: ContractA memeriksa lagi—saldo ContractB masih 1 Ether (karena pembaruan belum dilakukan). Ia kembali mengirim 1 Ether dan mengaktifkan fallback lagi.
Proses ini diulang terus-menerus sampai ContractA kehabisan Ether. Itulah mengapa reentrancy sangat berbahaya.
Analisis kode serangan secara spesifik
Untuk memahami lebih dalam, mari kita lihat contoh konkret dengan smart contract EtherStore. Contract ini memiliki dua fungsi utama:
Fungsi withdrawAll() dilakukan secara berurutan: memeriksa (saldo > 0), mengirim Ether, lalu mengatur saldo menjadi 0.
Itulah celahnya. Karena pengiriman Ether terjadi sebelum pembaruan saldo, penyerang memiliki peluang untuk mengintervensi.
Contract Attack dirancang untuk mengeksploitasi hal ini. Ia memiliki:
Proses serangan sangat sederhana:
Tiga teknik perlindungan terhadap serangan reentrancy
Teknik 1: Menggunakan Modifier nonReentrant
Cara paling sederhana untuk melindungi satu fungsi adalah dengan menggunakan modifier nonReentrant. Modifier adalah jenis fungsi khusus dalam Solidity yang memungkinkan Anda menambahkan kondisi atau fungsi tambahan ke fungsi lain tanpa menulis ulang logika lengkapnya.
Cara kerja nonReentrant:
Kelemahan: nonReentrant hanya melindungi satu fungsi saja, tidak mencegah serangan reentrancy silang antar fungsi berbeda.
Teknik 2: Pola check-effect-interaction
Ini adalah cara yang lebih canggih untuk melindungi banyak fungsi. Alih-alih mengunci kontrak, Anda mengubah urutan eksekusi kode.
Polanya meliputi:
Bandingkan kode yang rentan terhadap serangan dengan kode yang aman:
Dengan menempatkan pembaruan saldo segera setelah pemeriksaan, Anda memastikan bahwa bahkan jika ada panggilan balik, saldo sudah diperbarui terlebih dahulu, sehingga mencegah serangan.
Teknik 3: GlobalReentrancyGuard untuk banyak kontrak
Teknik ini cocok untuk proyek dengan banyak smart contract yang berinteraksi satu sama lain. Ide utamanya adalah membuat sebuah kontrak pusat yang membantu memeriksa reentrancy di seluruh sistem.
Alih-alih setiap kontrak memiliki variabel kunci sendiri, semua merujuk ke GlobalReentrancyGuard. Ini memungkinkan:
Contohnya: jika ScheduledTransfer mengirim Ether ke AttackTransfer, fungsi fallback AttackTransfer bisa mencoba memanggil kembali fungsi lain di ScheduledTransfer. GlobalReentrancyGuard akan mendeteksi dan memblokir ini.
Memilih teknik perlindungan yang sesuai
Gunakan nonReentrant ketika:
Gunakan pola check-effect-interaction ketika:
Gunakan GlobalReentrancyGuard ketika:
Cara terbaik adalah menggabungkan ketiga teknik ini sesuai kebutuhan spesifik bagian-bagian dalam proyek Anda.
Kesimpulan
Serangan reentrancy tidaklah terlalu sulit untuk dicegah, selama Anda memahami cara kerjanya dan menerapkan teknik yang tepat. Dari modifier nonReentrant yang sederhana hingga perlindungan menyeluruh dengan GlobalReentrancyGuard, setiap alat memiliki peran penting dalam ekosistem keamanan smart contract.
Ingatlah bahwa keamanan bukanlah pilihan, melainkan keharusan. Dengan memahami serangan reentrancy dan mengimplementasikan perlindungan yang sesuai, Anda dapat membangun smart contract yang aman dan efisien.
Untuk mendapatkan pembaruan tentang keamanan Web3, Solidity, pengujian smart contract, dan isu terkait lainnya, ikuti @TheBlockChainer di Twitter.