Re-Entrancy (Yeniden Giriş) Atağı

Re-Entrancy (Yeniden Giriş) Atağı

2016'daki meşhur DAO Hack'ine sebep olan atağı ve bu ataktan nasıl korunulacağını öğrenmeye ne dersiniz?

·

3 min read

Akıllı kontratlar hayatımıza girdiğinden beri bu alanda birçok “hack” yaşandı ve milyonlarca dolarlar kayıplara karıştı. Bunların belki de en kritiği 2016 yılında yaşandı, yaklaşık 3.6 Milyon ETH hacklendi. Hatta bu hack nedeniyle Ethereum ağında bir fork yaşandı. (Ethereum - Ethereum Classic).

Günümüzdeki bedeli milyarlarca dolar olan bu güvenlik açığının sebebi ise aslında çok basitti. Bu yazıda re-entrancy (yeniden giriş) atağının çalışma mantığını ve önlenme yöntemlerini anlatacağım.

Ön Bilgi

Anlaşılabilirlik açısından fallback fonksiyonu hakkında bilgi sahibi olmak faydalı olacaktır.

Bir akıllı kontratta tanımlı fonksiyonlar dışında bir fonksiyon çalıştırılmaya çalışılırsa veya o akıllı kontrata ETH (daha doğrusu ilgili ağın para birimi) gönderilirse bir problem yaşanmaması adına fallback adı verilen fonksiyonlar kullanılır. Böyle bir durumda fallback fonksiyonu çalışır.

Bizim için burada önemli olan kısım bir akıllı kontrata ETH gönderildiği zaman, o ilgili akıllı kontratta fallback fonksiyonu içerisinde yazılan kodların çalışmasıdır.

Çalışma Mantığı

Bir akıllı kontrata ETH gönderildiği zaman, o akıllı kontratın fallback fonksiyonunun içerisinde yazılan kodların çalıştığını öğrendik.

Ana aktörlerimiz iki adet kontrat.

  • Saldırıya açık, bir protokole ait, içinde kullanıcıların ETH’leri bulunan bir akıllı kontrat (Contract X).

  • Hacker’ın oluşturduğu, Contract X’e saldıracak olan akıllı kontrat (Contract Y)

Bir kişi/kontrat Contract X’ten para çekmek için withdraw() fonksiyonu çalıştırdığında, kontratın sırasıyla checkBalance(), sendFunds(), updateBalance() fonksiyonlarını çalıştırdığını varsayalım.

  • checkBalance(): Çekim yapılmak istenen miktar, çekim yapacak adresin bakiyesinden fazla mı değil mi kontrolü yapıyor.

  • sendFunds(): İlk kontrol başarılıysa çekim yapılmak istenen miktar, ilgili adrese gönderiliyor.

  • updateBalance(): Çekim işlemi gerçekleşince ilgili adresin bakiyesi güncelleniyor.

Her şey normal gözükmesine rağmen, ya hack’i yapmak isteyen Contract Y kontratının fallback fonksiyonunda da Contract X kontratının withdraw() fonksiyonu çağırılıyorsa?

X akıllı kontratının sendFunds() fonksiyonu çalışır çalışmaz, updateBalance() fonksiyonu çalışmadan önce, Y akıllı kontratının fallback fonksiyonu devreye girer. Kullanıcının bakiyesi güncellenmeden tekrar çekim isteği yapılır. checkBalance() kontrolünde yine çekim izni verileceği için (bakiye henüz güncellenmedi) Contract Y yatırdığı miktardan çok daha fazla çekim işlemi yapabilmiş olur. Bu döngü Contract X’deki tüm paralar çalınana kadar devam eder.

Kaynak: CryptoMarketPool

Bu yöntem ile gerçekleştirilen bazı hack’ler.

  • DAO Hack → 60 Milyon Dolar (Haziran 2016)

  • Uniswap/Lendf.Me → 25 Milyon Dolar (Nisan 2020)

  • The BurgerSwap → 7.2 Milyon Dolar (Mayıs 2021)

  • The SURGEBNB → 4 Milyon Dolar (Ağustos 2021)

  • CREAM FINANCE → 18.8 Milyon Dolar (Ağustos 2021)

  • Siren protocol → 3.5 Milyon Dolar (Eylül 2021)

  • Fei Protocol → 80 Milyon Dolar (Nisan 2022)

Alınabilecek Önlemler

Bu saldırıyı önlemek için birkaç farklı yöntem var. Bunlardan iki tanesini paylaşacağım.

  1. Bakiye güncellemesini, ETH göndermeden önce yapmak

Bakiye güncellemesi eğer ETH gönderiminden önce yapılırsa, hacker birden çok kez çekim işlemi denese bile gerçekleşmeyecektir.

Burada aklınıza “Peki ya bakiye güncellendikten sonra çekim işleminde aksilik çıkarsa ne olacak?” sorusu gelecektir. Aşağıdaki örneği incelerseniz

,requirekomutu sayesinde transfer işlemi başarısız olursa ilgili işlem revert edileceği için çekim işleminde hata olursa bakiye de tekrar eski haline dönecektir.

Saldırıya açık olmayan bir akıllı kontrat örneği

Saldırıya açık olmayan bir akıllı kontrat örneği

  1. ReentrancyGuard modülünü kullanmak

OpenZeppelin’in ReentrancyGuard modülünün nonReentrant modifier’ı kullanılarak da önlem almak mümkün.

nonReentrant modifier’ı uygulandığı fonksiyona yeniden girişi engeller. Çalışma mantığı da kısaca aşağıdaki gibidir:

nonReentrant modifier

Sonuç

Çok basit gözüken bu çözümler zamanında yapılmadığı için milyonlarca dolarlık hack’ler yaşandı. Kod yazarken güvenlik önlemlerine çok dikkat etmeliyiz, çünkü ufak bir hata milyon dolarlarca kayıplara yol açabilir.

İleride bu anlattığım yöntemlerle ilgili örnek bir kod çalışması da yapabiliriz. Eğer böyle bir çalışma görmek isterseniz yorumlarda belirtirseniz çok sevinirim!

Hepinize mutlu günler.

https://hacken.io/discover/reentrancy-attacks/

https://blog.chain.link/reentrancy-attacks-and-the-dao-hack/

https://learnweb3.io/courses/c446d19f-a25d-42c6-b3e4-4311c5040587/lessons/9e9b8ea7-156e-45ba-8540-5f86a9b8ccc2

Did you find this article valuable?

Support Buildchain by becoming a sponsor. Any amount is appreciated!