BNB Chain安全开發,這10大實用tips一定要收藏
BNB Chain 是Web3世界中最受歡迎的區塊鏈之一,其費用合理、交易迅速以及項目生態系統豐富幾大原因吸引了廣大用戶。與任何的區塊鏈都一樣, BNB Chain 上的开發者在开發過程中首先考慮的應該是安全問題:因為任何資金的損失都會導致用戶對協議及平臺的信心減弱,而安全漏洞和黑客攻擊是开發者面臨的最大風險之一。
在本文中,我們提供了十大實用安全 tips,讓开發者可以在 BNB Chain 上減少風險並开發更安全的智能合約。
01
╱ 定義 ╱
重放攻擊(Replay Attacks)又稱重播攻擊、回放攻擊,是區塊鏈環境中一種常見的攻擊類型。在網絡安全中,“重放攻擊"”是一種網絡攻擊類型,其中有效的數據傳輸被惡意或欺詐性地重復或延遲。
在Web3和智能合約的環境背景下,這通常意味着攻擊者能夠在未經原始用戶允許的情況下重復智能合約中的交易或操作。這可能會導致各種形式的欺詐,如雙重支付等。
這些攻擊會給用戶和开發者帶來嚴重的後果,因為它們允許攻擊者重復使用相同的籤名,以獲得智能合約上所有資金或其他資產的未授權訪問。
為了防止重放攻擊,开發人員必須仔細設計和實現他們的智能合約代碼,並遵循籤名驗證以及行業最佳安全標准。
02
╱ 案例解析 ╱
以下代碼片段表示了 BNB 鏈上一個代幣的轉移 transfer 實現過程。該代碼很容易受到重放攻擊,從而使得攻擊者能夠重復使用同一個籤名。
這個功能缺乏 nonce 或重放保護,允許攻擊者多次“重放”一個已籤名的轉账交易。攻擊者可以攔截已籤署的交易,並再次將其發送到同一個合約或另一個合約,而合約仍會認為它是有效的,因此攻擊者就可能利用該漏洞竊取資產。
03
╱ 改進方法 ╱
在籤名中增加一個 nonce 或使用 mapping 變量來記錄籤名。其中更具地的解決方案會根據項目設計的不同而不同。
01
╱ 定義 ╱
當一個惡意合約在初始調用完成之前反復調用一個易受攻擊的合約時,就會發生重入攻擊。換句話說,攻擊者可以“欺騙”一個易受攻擊的合約,使其認為它已經完成了一個交易並可以自由地進入下一個交易,但實際上它仍然在執行攻擊者的惡意代碼。
這可能導致攻擊者能夠以意想不到的方式操縱合約的狀態,並有可能獲得未經授權的資金。
02
╱ 案例解析 ╱
在下面的代碼片段中,用戶可以通過調用提款 withdraw 函數並指定他們要提取的金額來從他們的账戶中提取資金。然而,由於 withdraw 函數沒有防止對該函數的遞歸調用,因此很容易遭到重入攻擊。
攻擊者可以通過創建一個惡意合約,在余額真正從其账戶扣除之前多次調用 withdraw 函數來利用漏洞。函數 msg.sender.call 向惡意合約發送資金,攻擊者通過惡意合約的 receive()函數在其余額減少到零之前反復提取資金,從而耗盡受害者合約的所有資金。
03
╱ 改進方法 ╱
在任何外部調用之前進行狀態更新。
該模式被稱為“檢查-影響-交互(Check-Effects-Interact)”模式,是一種用於防止智能合約中重入攻擊的設計模式。該模式通過先檢查前提條件,然後在進行任何外部調用之前更新狀態,將狀態變化與其他合約的外部調用分开。這樣一來,如果一個外部調用觸發了一個試圖回調到合約的回調,但狀態已經被更新了,因此可以防止其他意外影響。
通過遵循這種模式,开發者可以確保他們的合約更安全,更不容易受到重入式攻擊。
另一個可能的修復方法則是利用 modifier 來限制對同一函數的多次調用,這很像 OpenZeppelin 的 ReentrancyGuard。
01
╱ 定義 ╱
預言機可以幫助智能合約從區塊鏈外部檢索信息。通常去中心化的交易所(DEX)資產的價格是由預言機從 DEX 最後一次成功交易中提取出的價格而決定的。
然而問題來了,該價格可能被任何人輕易操縱,導致智能合約出現問題。我們經常會看到通過閃電貸操控價格預言機的案例,原因是閃電貸允許用戶只要在同一區塊內償還貸款,就可以無抵押借入巨額資金。這樣攻擊者就可以很容易地影響甚至操控價格,從虛假清算、過度貸款或不公平交易中獲利。
02
╱ 案例解析 ╱
以下是一個容易受到預言機操縱攻擊的代碼片段。
該合約允許用戶使用路由合約將代幣 A 換成代幣 B,但它依賴外部預言機( Uniswap Pair 合約)來獲得代幣 A 和代幣 B 的儲備以計算價格。攻擊者能夠操縱 Uniswap Pair 合約的儲備以及 getAmountOut 函數,最終導致交換以不合理的價格執行。
03
╱ 改進方法 ╱
為了防止這種攻擊,开發者應該使用可獲取鏈上中心化和去中心化交易所成交量加權平均價格(VWAP)或時間加權平均價格(TWAP)的去中心化預言機網絡。這樣一來,數據將從多個數據源和廣泛的時間內進行收集,從而使代碼更不容易受到攻擊和操縱的影響。對於开發者來說,能夠刪除智能合約中任何操縱預言機的攻擊載體以防止潛在漏洞十分重要。
01
╱ 定義 ╱
正確設置函數的可見性可確保智能合約的安全性和完整性。使用不正確的函數可見性設置會允許非預期用戶操縱合約狀態,從而導致資金被盜或合約功能被控制等嚴重問題。
通過將函數的可見性設置為私有或內部,可確保开發者對某些函數的訪問有一定限制,僅有授權方才可以調用這些函數。私有函數只能從合約本身調用,而內部函數也可以從沿用當前合約中調用。這允許开發者在保持控制訪問功能權限的同時可創建具有更強大功能且更復雜的合約。
02
╱ 案例解析 ╱
函數 setAdmin()允許任何人將任何地址設置為合約管理員。根據合約內授予管理地址的權限,這有可能導致开發者失去對合約本身的控制甚至資金造成損失。
通過將函數的可見性設置為 internal 內部,某些合約函數在內部就可能允許將某些用戶設置為管理員。
03
╱ 改進方法 ╱
訪問 modifier 是一個重要的安全功能,它可以規定誰可以訪問合約中的特定功能或變量。這些 modifier 可被用來限制某些函數或變量對特定角色或地址的可見性,並防止惡意行為者未經授權進行訪問或操縱合約狀態。
例如,某合約可能有一個只有合約所有者才可以調用的函數,或者有一個只能由一組特定地址訪問的變量。
通過將可見性 modifier 改成 external,並將訪問 modifier 設置為 onlyOwner,可將對 setAdmin 函數的訪問限制在合約所有者的地址當中。這將防止惡意的外部方控制某些特權功能。
正確使用可見性和限制性 modifier 可以令合約管理變得更加容易,也可以減少常見的如重入式攻擊(攻擊者反復調用一個函數來操縱合約狀態)或前置運行攻擊(攻擊者監控未決交易並在合法交易執行前操縱合約狀態)而帶來的問題。
通過適當地使用這些功能,开發人員可以增強他們的合約安全性和可靠性,減少未經授權訪問的風險,並提高他們代碼整體質量和可維護性。
01
╱ 定義 ╱
在決定未來是否要對合約升級性時,初始時就要仔細考慮合約的設計。合約可升級性是指在智能合約被部署到區塊鏈上後,具有可被修改或更新其邏輯的性質。雖然可升級性可以提供許多優勢(如修復錯誤,提高效率或增加新的功能等),但它同時也引入了一些風險。合約升級可能導致引入新的漏洞、增加合約復雜性,或造成意外的後果。
因為代理管理員可以在沒有得到社區共識的情況下升級合約,因此合約可升級性也引發了信任問題。开發者需要仔細權衡可升級性的優勢和劣勢,並確定自己的項目是否真正有必要引入可升級合約。在某些情況下,設計一個從一开始就打定主意不可改變的合約而不是依賴以後的修改能力,會更加安全。
02
╱ 改進方法 ╱
當涉及到合約的可升級性時,有幾個重要的做法需要遵循。首先,最重要的是不要修改 proxy library。Proxy 合約庫極具復雜性,特別是在存儲管理和升級機制方面。即使是小錯誤也會大大影響 Proxy 和邏輯合約的運行。事實上,在審計過程中發現的許多與 proxy 相關的嚴重性錯誤都是由不恰當修改 proxy 庫造成的。
合約可升級性的另一個關鍵做法是在基本合約中包含一個存儲“間隙”。邏輯合約則必須在合約代碼中包含一個存儲間隙,以考慮到在部署新的邏輯實現時可能引入的新變量。在添加新的狀態變量後,更新“間隙”的大小就變得更加重要了。這種做法可以確保未來的升級能夠順利進行,不會出現問題。
最後,必須避免使用 selfdestruct()或對不受信任的合約執行 delegatecall()/ call()。攻擊者可以利用這些函數來破壞邏輯實現或執行自定義邏輯。為了防止這種情況,驗證用戶的輸入很重要!不要允許合約對不受信的合約執行 delegatecall()/ call()。此外,不建議在邏輯合約中使用 delegatecall(),因為在多個合約中管理存儲布局會很困難。通過遵循這些做法,开發者可以在他們的合約升級中最大限度地減少漏洞及風險。
01
╱ 定義 ╱
搶先交易( Front -Running),一直是一個頑固且不容易解決的問題,用戶能夠利用提交交易和區塊鏈上確認交易之間的延遲來獲利。這種延遲是由 mempool 造成的。
mempool 是一個臨時存儲區,用於存儲已廣播到網絡的未確認交易。網絡中的所有節點都保持着一個 mempool,允許任何人看到待定交易,並有可能攔截從而從中獲利。mempool 還為礦工提供了一個重新安排交易的機會,以使他們的利潤最大化,創造所謂的礦工(或最大)可提取價值(MEV)。
02
╱ 案例解析 ╱
下面是一個容易出現搶先交易的拍賣出價功能的例子。
這個功能允許用戶在拍賣中出價,但它可能會受到搶先交易攻擊。假設一個惡意用戶監控區塊鏈時,看到另一個用戶已經提交了一個高價,於是這個惡意用戶可以迅速提交一個更高的出價並被優先處理,最終贏得拍賣。
在以下版本中,用戶提交不為人知的出價價格,而這些出價被存儲在一個 mapping 中。出價金額在競價期結束前都是加密的。
03
╱ 改進方法 ╱
在競價期結束時,用戶可以通過提交原始競價金額和一個祕密值來揭示他們的競價。合約驗證出價金額和保密的哈希值與存儲的祕密出價相符,確保出價是在競價期結束前提交的。如果該出價高於當前的最高出價,它就成為新的最高出價。通過在競價期結束前掩蓋出價金額,該功能可以緩釋搶先交易攻擊。
搶先交易和 MEV 已經成為區塊鏈社區的主要關注點,各種解決方案,如交易和公平排序服務(FSS),已經被提出來解決這些問題。交易可以通過對其他用戶隱藏交易細節,直到交易在區塊鏈上執行,來幫助預防搶先交易。另一方面,FSS 可以通過安全的鏈下交易排序來減少搶先交易和 MEV 的影響。
制定一個明確而全面的響應計劃對於處理緊急安全事件至關重要。該計劃應定期審查、更新,並測試其有效性。在發生緊急安全事件時,時間是最重要的。因此該計劃應提前定制並包括識別、控制和緩釋等細節操作步驟。
該計劃應有效到位,讓所有利益相關方了解情況。同時,定期備份數據對於防止數據丟失也很重要。計劃中需概述將數據和系統恢復至從前狀態的恢復過程。團隊成員應接受針對該計劃的系統培訓,以確保每個人都了解自己的角色和責任。
一個精心准備的響應計劃或許不能亡羊補牢,但卻可以將事件的影響降到最低,並保持與用戶和利益相關者的信任度。
常規的代碼審計對於維護應用程序的安全至關重要。與專門從事智能合約安全的專業審計師合作是开發過程中的一個重要步驟。審計人員將檢查代碼中的漏洞,並為提高整體安全性提供建議。
優先考慮和解決已發現的問題,並與審計人員保持开放的溝通,對於提高安全性至關重要。
除此之外,與審計人員的溝通也很關鍵。審計人員可以詳細解釋他們發現的問題及漏洞,並就如何解決該漏洞提供指導和實用性幫助。通過與專業審計機構/人員的合作,安全將“更上一層樓”。
對 BNB 鏈的开發者來說,進行常規審計是任何一個全面的安全策略都不可或缺的組成部分。主動識別和解決代碼中的漏洞可以將安全漏洞的風險降到最低。
使用賞金計劃是激勵社群白帽黑客報告項目代碼中安全漏洞的一個有效方法。通過提供如代幣或其他獎勵等激勵,任何項目都可以鼓勵有經驗的人檢查代碼並報告他們發現的任何潛在問題。
制定一個明確、透明的漏洞賞金計劃十分重要。其中計劃需要包含:發現哪些類型的漏洞有資格獲得獎勵,如何評估這些漏洞的價值等。同時,在漏洞賞金計劃中加入有公信力的第三方可以幫助確保該計劃的順利運行和獎勵的公平分配。
同時,擁有一個多樣化的“賞金獵人小組”也很重要。不同的白帽黑客有着不同的擅長領域,可以專注於發現其他人可能錯過的問題。
最後,一旦報告了漏洞,就必須迅速有效地採取行動來解決這些漏洞。賞金計劃可以成為識別漏洞的有效工具,但必須由开發團隊來實際修復問題才有意義。
對Web3用戶進行安全性教育,是建立一個安全生態系統的關鍵步驟。保證客戶的安全,就有助於保證平臺的安全。用戶應該接受教育,了解保護他們账戶和敏感信息的最佳做法。
其中最重要的環節則是學會如何避免網絡釣魚詐騙。
網絡釣魚詐騙犯,會通過冒充合法網站或服務來欺騙用戶,使用戶泄露私鑰或密碼。 CertiK 建議用戶在收到任何信息時,始終要仔細檢查任何郵件、來源等正在使用的網站 URL,並且永遠不要在不信任的網站上輸入私人密鑰或密碼。
而另一個重要部分則是擁有安全且強大的密碼。CertiK 在此建議用戶為每個账戶使用獨特和復雜的密碼,並避免在不同的服務中重復使用密碼。同時,還應使用密碼管理器或其他安全存儲機制來安全地存儲密碼。
最後,保護私鑰極為重要。私鑰相當於用戶的密碼,應該在任何時候都保證不被其他人接觸到。用戶應避免與任何人分享他們的私鑰,並將其存放在一個安全的地方。
總結
在 BNB Chain 上構建智能合約和 dApps 的开發者必須採取全面的安全方法來保證其用戶資金和資產的安全。更重要的是,在處理安全漏洞時要主動出擊,而不是被動應付;在漏洞發生時甚至之前就要制定計劃,並對所有相關用戶和利益相關者進行適當的安全教育。通過結合所有以上措施,可以幫助項目大大減少安全漏洞和黑客攻擊的風險。
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播信息之目的,不構成任何投資建議,如有侵權行為,請第一時間聯絡我們修改或刪除,多謝。