Akıllı Sözleşme Güvenliği: Yeniden Giriş Açıklarını Anlamak ve Önlemek

Reentrancy saldırıları, akıllı sözleşme geliştirmede en önemli güvenlik tehditlerinden birini temsil etmektedir. Bu teknik analiz, reentrancy zafiyetlerinin arkasındaki mekanizmaları açıklar ve sözleşmelerinizi korumak için kapsamlı savunma stratejileri sunar.

Reentrancy Saldırısı Nedir?

Reentrancy, bir akıllı sözleşmedeki bir fonksiyonun, yürütülmesi sırasında kesintiye uğrayabilmesi ve ilk çağrı tamamlanmadan tekrar çağrılabilmesi durumudur. Teknik terimlerle, reentrancy, dış çağrılar aracılığıyla kontrol akışını manipüle ederek bir akıllı sözleşmenin yürütme bağlamını istismar eder.

Sözleşme A, Sözleşme B ile etkileşime girdiğinde, zafiyet ortaya çıkar çünkü Sözleşme B, Sözleşme A'nın yürütülmesi hala devam ederken Sözleşme A'ya geri çağrı yapabilir. Bu özyinelemeli çağrı modeli, sözleşme durumunu manipüle etmek ve fonları boşaltmak için silahlandırılabilir.

Saldırı Mekanikleri: Reentrancy Nasıl Çalışır

İki sözleşmenin bulunduğu bir senaryoyu düşünün:

  • Sözleşme A: 10 ETH tutan savunmasız bir sözleşme
  • Kontrat B: Kontrat A'ya 1 ETH yatırılmış kötü niyetli bir kontrat

Saldırı akışı bu deseni izler:

  1. Sözleşme B, Sözleşme A'daki withdraw() fonksiyonunu çağırır.
  2. Sözleşme A, Sözleşme B'nin bakiyesinin 0'dan büyük olduğunu doğrular (kontrolü geçer)
  3. Sözleşme A, bakiye kaydını güncellemeden önce Sözleşme B'ye 1 ETH gönderir.
  4. ETH transferi, Sözleşme B'nin geri dönüş fonksiyonunu tetikler.
  5. Fallback fonksiyonu içinde, Sözleşme B, Sözleşme A'nın withdraw() fonksiyonunu tekrar çağırır.
  6. Çünkü Sözleşme A, Sözleşme B'nin bakiyesini henüz güncellemediğinden, kontrol tekrar geçiyor.
  7. Contract A, Contract B'ye başka bir ETH gönderir
  8. Bu döngü, Sözleşme A'nın fonları tükenene kadar tekrar eder.

Kritik güvenlik açığı, Sözleşme A'nın yürütme sırasındadır: dış çağrıyı ( ETH) göndermeden önce, iç durumu güncellemektedir ( bakiyeyi sıfıra ayarlamaktadır ).

Yeniden Girişe Karşı Üç Savunma Tekniği

1. Fonksiyon Seviyesi Koruma noReentrant Modificeri ile

noReentrant modifiyeri, bir fonksiyonun özyinelemeli olarak çağrılmasını önleyen bir kilitleme mekanizması uygular:

katılık // Yeniden girişimi takip etmek için durum değişkeni bool özel locked = false;

// Yeniden girişimi önlemek için modifikatör modifier noReentrant() { require(!locked, "Reentrant call"); kilitli = true; _; kilitli = false; }

// Korunan fonksiyon function withdraw() public noReentrant { // Fonksiyon mantığı burada }

Bu yaklaşım, korunan işlevlerin eşzamanlı yürütülmesini engelleyen, sözleşme genelinde bir durum değişkeni tutarak yeniden girişim girişimlerini engeller.

2. Kontrol-Etkileşim-Deseni

Bu desen, kodu belirli bir işlem sırasını takip edecek şekilde yeniden yapılandırır:

  1. Kontrol: Koşulları doğrulayın (örneğin, bakiye > 0)
  2. Etki: Durum değişkenlerini güncelle (örn., bakiyeyi ayarla = 0)
  3. Etkileşim: Harici çağrılar yapın (örneğin, ETH transferi)

Hassas kod ile korunan kodun karşılaştırılması:

Hassas: katılık function withdraw() external { uint bal = balances[msg.sender]; require(bal > 0);

// Etki Öncesi Etkileşim (vulnerable)
(bool gönderildi, ) = msg.sender.call{value: bal}("");
require(sent, "Ether gönderimi başarısız");

balances[msg.sender] = 0; // Yeniden giriş olursa asla ulaşılamayabilir

}

Korunan: katılık function withdraw() external { uint bal = balances[msg.sender]; require(bal > 0);

// Etki Etkileşimden Önce (secure)
bakiye[msg.sender] = 0;

(bool gönderildi, ) = msg.sender.call{value: bal}("");
require(sent, "Ether gönderilemedi");

}

Dış etkileşimlerden önce durumu güncelleyerek, sözleşme dış çağrının yeniden giriş fonksiyonu çağrısını tetiklemesi durumunda bile güvenli kalır.

3. GlobalReentrancyGuard ile Çapraz Sözleşme Koruması

Birden fazla etkileşimde bulunan sözleşmelere sahip projeler için, paylaşılan bir reentrancy guard kapsamlı koruma sağlar:

katılık // Yeniden giriş koruması için merkezi sözleşme sözleşme GlobalReentrancyGuard { mapping(adres => bool) özel _durum;

function _beforeNonReentrant() internal {
    require(_status[msg.sender] == false, "ReentrancyGuard: reentrant call");
    _status[msg.sender] = true;
}

function _afterNonReentrant() internal {
    _status[msg.sender] = false;
}

}

// Bir sözleşmede koruyucuyu kullanma sözleşme ProtectedContract GlobalReentrancyGuard'dır { function protectedFunction() external { _beforeNonReentrant();

    // Korunan fonksiyon mantığı burada
    
    _afterNonReentrant();
}

}

Bu teknik, ekosisteminizdeki birden fazla sözleşme arasındaki yürütme durumunu takip eden küresel bir durum kaydı tutarak, çapraz sözleşme yeniden girişimini önler.

Güvenlik En İyi Uygulamaları

Reentrancy saldırılarına karşı kapsamlı koruma sağlamak için:

  1. Birden fazla savunma katmanı uygulayın: Maksimum güvenlik için kontrol-etki-etkileşim desenini reentrancy korumaları ile birleştirin
  2. Kapsamlı testler yapın: Potansiyel reentrancy açıklarını tespit etmek için Mythril gibi özel araçlar kullanın.
  3. Belirlenen kalıpları takip edin: Projenizdeki tüm sözleşmelerde güvenlik önlemlerini tutarlı bir şekilde uygulayın
  4. Denetlenen bağımlılıkları kullanın: Kanıtlanmış güvenlik kayıtlarına sahip, savaşta test edilmiş kütüphaneleri entegre edin
  5. Önce bakiyeleri güncelle: Her zaman dış çağrılar veya transferler gerçekleştirmeden önce durumu değiştirin.

Bu savunma mekanizmalarını uygulayarak, akıllı sözleşmelerinizi blockchain güvenliğindeki en tehlikeli saldırı vektörlerinden birine karşı etkili bir şekilde koruyabilirsiniz.

ETH5.45%
View Original
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
  • Reward
  • Comment
  • Repost
  • Share
Comment
0/400
No comments
  • Pin
Trade Crypto Anywhere Anytime
qrCode
Scan to download Gate App
Community
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)