به خطر افتادن امنیت قرارداد هوشمند با reentrancy attack

reentrancy attack یکی از مخرب ترین حملات در قرارداد هوشمند Solidity است. حمله ورود مجدد یا reentrancy attack زمانی اتفاق میافتد که یک تابع یک تماس خارجی با قرارداد غیرقابل اعتماد دیگری برقرار میکند. سپس قرارداد نامطمئن در تلاش برای تخلیه وجوه، یک فراخوان بازگشتی به تابع اصلی ایجاد می کند.
زمانی که قرارداد نتواند وضعیت خود را قبل از ارسال وجوه به روز کند، مهاجم می تواند به طور مداوم تابع برداشت را برای تخلیه وجوه قرارداد فراخوانی کند. یک حمله Reentrancy معروف در دنیای واقعی، حمله DAO است که باعث ضرر 60 میلیون دلاری آمریکا شد.
آیا reentrance attack همچنان یک مشکل مهم است؟
اگرچه حمله به ورود مجدد در دو سال گذشته بسیار قدیمی در نظر گرفته شده است، مواردی مانند موارد زیر وجود داشته است:
هک های Uniswap/Lendf.Me (آوریل 2020) – 25 میلیون دلار، مورد حمله یک هکر با استفاده از ورود مجدد.
هک BurgerSwap (مه 2021) – 7.2 میلیون دلار به دلیل یک قرارداد توکن جعلی و سوء استفاده از ورود مجدد.
هک SURGEBNB (اوت 2021) – به نظر می رسد 4 میلیون دلار یک حمله دستکاری قیمت مبتنی بر ورود مجدد باشد.
هک CREAM FINANCE (اوت 2021) – 18.8 میلیون دلار، آسیب پذیری ورود مجدد به بهره بردار اجازه وام دوم را داد.
هک پروتکل Siren (سپتامبر 2021) – 3.5 میلیون دلار، استخرهای AMM از طریق حمله به ورود مجدد مورد سوء استفاده قرار گرفتند.
Reentrancy Attack چگونه کار می کند؟
Reentrancy Attack شامل دو قرارداد هوشمند است. یک قرارداد آسیب پذیر و یک قرارداد مهاجم غیرقابل اعتماد.

سناریوی Reentrancy Attack
قرارداد هوشمند آسیب پذیر دارای 10 eth است.
یک مهاجم با استفاده از تابع سپرده، 1 eth را ذخیره می کند.
یک مهاجم تابع برداشت را فراخوانی می کند و به یک قرارداد مخرب به عنوان گیرنده اشاره می کند.
اکنون تابع برداشت بررسی می کند که آیا می توان آن را اجرا کرد:
آیا مهاجم 1 ثانویه در تعادل خود دارد؟
بله – به دلیل سپرده آنها.
انتقال 1 eth به یک قرارداد مخرب.
(توجه: موجودی مهاجم هنوز به روز نشده است)
تابع بازگشتی در تماس های دریافتی مجدداً عملکرد را لغو می کند.
1. اکنون تابع برداشت بررسی می کند که آیا می توان آن را اجرا کرد:
آیا مهاجم 1 ثانویه در تعادل خود دارد؟بله – زیرا موجودی به روز نشده است.
انتقال 1 eth به یک قرارداد مخرب.
و دوباره تا زمانی که مهاجم تمام وجوه ذخیره شده در قرارداد را تخلیه کند.
در زیر قرارداد وجود دارد که حاوی آسیبپذیری مجدد است.
}contract DepositFunds
;mapping(address => uint) public balances
} function deposit() public payable
; balances[msg.sender] += msg.value
{
}function withdraw() public
; uint bal = balances[msg.sender]
; require(bal > 0)
;(bool sent, ) = msg.sender.call{value: bal}(“”)
;require(sent, “Failed to send Ether”)
; balances[msg.sender] = 0
{
{
این آسیبپذیری زمانی ایجاد میشود که مقدار اتر درخواستی کاربر را ارسال میکنیم.در این حالت، مهاجم تابع ()retract را فراخوانی می کند. از آنجایی که موجودی او هنوز روی 0 تنظیم نشده است، او می تواند توکن ها را منتقل کند، حتی اگر قبلا توکن ها را دریافت کرده باشد.
حال، بیایید یک مهاجم بدخواه را در نظر بگیریم که قرارداد زیر را ایجاد کرده است.
}contract Attack
; DepositFunds public depositFunds
} constructor(address _depositFundsAddress)
; depositFunds = DepositFunds(_depositFundsAddress)
{
// .Fallback is called when DepositFunds sends Ether to this contract
} fallback() external payable
} if (address(depositFunds).balance >= 1 ether)
; ()depositFunds.withdraw
{
{
} function attack() external payable
; require(msg.value >= 1 ether)
; () depositFunds.deposit{value: 1 ether}
; () depositFunds.withdraw
{
{
تابع حمله تابع برداشت در قرارداد قربانی را فراخوانی می کند. هنگامی که نشانه دریافت می شود، تابع بازگشتی تابع برداشت را فراخوانی می کند. از آنجایی که چک تایید میشود، قرارداد توکن را برای مهاجم ارسال میکند که تابع بازگشتی را فعال میکند.
چگونه از قرارداد هوشمند در برابر حمله مجدد محافظت کنیم؟
اطمینان حاصل کنید که همه تغییرات حالت قبل از فراخوانی قراردادهای خارجی رخ می دهد، به عنوان مثال، قبل از فراخوانی کد خارجی، موجودی یا کد را به صورت داخلی به روز کنید.
از اصلاح کننده های عملکردی استفاده کنید که از ورود مجدد جلوگیری می کند.
اصلاح کننده برای جلوگیری از حمله مجدد ورود
} contract ReEntrancyGuard
; bool internal locked
} () modifier noReentrant
; require(!locked, “No re-entrancy”)
;locked = true
;_
; locked = false
{
{

در صورتی که تجربه خاصی در خصوص برنامهنویسی ندارید میتوانید از دورههای رایگان سایت ما “فرازمان“، استفاده کنید. همچنین اگر به دورههای پیشرفتهتری در این خصوص نیاز داشته باشید، ما با آموزش های حرفه ای که در سایتمان قرار دادیم می توانید به سطح دلخواهتان با تلاش و پشتکار برسید.
نقشه راه
راهنما آکادمی فرازمان
برای یادگیری برنامه نویسی بلاکچین…
در این باره بیشتر بخوانید
دیدگاهتان را بنویسید