以太坊智能合约安全 Dasp Top10
譯者:愛上平頂?
來源:慢霧區
原文鏈接:https://www.dasp.co/
這是分布式應?安全項?(或DASP)2018 年排名前10的漏洞第?次迭代
該項?是NCC集團的?項舉措。這是?個開放的合作項?,致?于發現安全社區內的智能合約漏洞。要參與,請加?github??。
1.重?漏洞
也被稱為 或與空?競爭,遞歸調?漏洞,未知調?
這種漏洞在很多時候被很多不同的?忽略:審閱者傾向于?次?個地審查函數,并且假定保護?例程的調?將安全并按預期運?。 Phil Daian
重?攻擊,可能是最著名的以太坊漏洞,第?次被發現時,每個?都感到驚訝。它在數百萬美元的搶劫案中?次亮相,導致了以太坊的分叉。當初始執?完成之前,外部合同調?被允許對調?合同進?新的調?時,就會發?重新進?。對于函數來說,這意味著合同狀態可能會在執?過程中因為調?不可信合同或使?具有外部地址的低級函數?發?變化。
損失:估計為350萬ETH(當時約為5000萬美元)
發現時間表:
2016年6?5??Christian Reitwiessner發現了?個堅定的反模式
2016年6?9??更多以太坊攻擊:Race-To-Empty是真正的交易(vessenes.com)
2016年6?12??在以太坊智能合約'遞歸調?'錯誤發現(blog.slock.it)之后,沒有DAO資??臨?險。
2016年6?17??我認為TheDAO現在正在流失(reddit.com)
2016年8?24??DAO的歷史和經驗教訓(blog.sock.it)
真實世界影響:
- DAO
示例:
代碼示例:
以下函數包含易受重?攻擊影響的函數。當低級別call()函數向msg.sender地址發送ether時,它變得易受攻擊; 如果地址是智能合約,則付款將觸發其備?功能以及剩余的交易?體:
function withdraw(uint _amount) { require(balances[msg.sender] >= _amount);msg.sender.call.value(_amount)();balances[msg.sender] -= _amount; }其他資源:
- DAO智能合約
- 分析DAO的利?
- 簡單的DAO代碼示例
- 重?代碼示例
- 有?試圖利?我們的智能合約中的?個缺陷,盜取它的?切
2.訪問控制
通過調?initWallet函數,可以將Parity Wallet庫合約變為常規多sig錢包并成為它的所有者。 Parity
訪問控制問題在所有程序中都很常?,?不僅僅是智能合同。事實上,這是OWASP排名前10位的第5位。?們通常通過其公共或外部功能訪問合同的功能。盡管不安全的可視性設置會給攻擊者直接訪問合同的私有價值或邏輯的?式,但訪問控制旁路有時更加微妙。這些漏洞可能發?在合約使?已棄?tx.origin的驗證調?者時,?時間處理?型授權邏輯require并delegatecall在代理庫或代理合約中魯莽使?。
損失:估計為150,000 ETH(當時約3000萬美元)
真實世界影響:
- 奇偶校驗錯誤1
- 奇偶校驗錯誤2
- Rubixi
示例:
代碼示例:
在下?的例?中,契約的初始化函數將函數的調?者設置為它的所有者。然?,邏輯與合約的構造函數分離,并且不記錄它已經被調?的事實。
function initContract() public {owner = msg.sender; }在Parity multi-sig錢包中,這個初始化函數與錢包本身分離并在“庫”合同中定義。?戶需要通過調?庫的函數來初始化??的錢包delegateCall。不幸的是,在我們的例?中,函數沒有檢查錢包是否已經被初始化。更糟糕的是,由于圖書館是?個聰明的合同,任何?都可以??初始化圖書館并要求銷毀。
其他資源:
- 修復Parity多信號錢包bug 1
- 奇偶校驗安全警報2
- 在奇偶錢包multi-sig hack上
- 不受保護的功能
- Rubixi的智能合約
3.算術問題
也被稱為 整數溢出和整數下溢
溢出情況會導致不正確的結果,特別是如果可能性未被預期,可能會影響程序的可靠性和安全性。 Jules Dourlens
整數溢出和下溢不是?類新的漏洞,但它們在智能合約中尤其危險,其中?符號整數很普遍,?多數開發?員習慣于簡單int類型(通常是有符號整數)。如果發?溢出,許多良性代碼路徑成為盜竊或拒絕服務的載體。
真實世界影響:
- DAO
- BatchOverflow(多個令牌)
- ProxyOverflow(多個令牌)
示例:
代碼示例:
最直接的例?是?個不檢查整數下溢的函數,允許您撤銷?限量的標記:
function withdraw(uint _amount) { require(balances[msg.sender] - _amount > 0);msg.sender.transfer(_amount);balances[msg.sender] -= _amount; }第?個例?(在?益的Solidity編碼競賽期間被發現)是由于數組的?度由?符號整數表示的事實促成的錯誤的錯誤:
function popArrayOfThings() { require(arrayOfThings.length >= 0);arrayOfThings.length--; }第三個例?是第?個例?的變體,其中兩個?符號整數的算術結果是?個?符號整數:
function votes(uint postId, uint upvote, uint downvotes) { if (upvote - downvote < 0) {deletePost(postId)} }第四個示例提供了即將棄?的var關鍵字。由于var將?身改變為包含指定值所需的最?類型,因此它將成為uint8保持值0.如果循環的迭代次數超過255次,它將永遠達不到該數字,并且在執?運?時停?出?:
for (var i = 0; i < somethingLarge; i ++) { // ... }其他資源:
- SafeMath防?溢出
- 整數溢出代碼示例
4.未檢查返回值的低級別調?
也稱為 或與靜默失敗發送,未經檢查發送
盡可能避免使?低級別的“調?”。如果返回值處理不當,它可能會導致意外的?為。Remix
其中的密實度的更深層次的特點是低級別的功能call(),callcode(),delegatecall()和send()。他們在計算錯誤??的?為與其他Solidity函數完全不同,因為他們不會傳播(或冒泡),并且不會導致當前執?的全部回復。相反,他們會返回?個布爾值設置為false,并且代碼將繼續運?。這可能會讓開發?員感到意外,如果未檢查到這種低級別調?的返回值,則可能導致失敗打開和其他不想要的結果。請記住,發送可能會失敗!
真實世界影響:
- 以太之王
- Etherpot
代碼示例:
下?的代碼是?個當忘記檢查返回值時會出錯的例?send()。如果調??于將ether發送給不接受它們的智能合約(例如,因為它沒有應付回退功能),則EVM將?其替換其返回值false。由于在我們的例?中沒有檢查返回值,因此函數對合同狀態的更改不會被恢復,并且etherLeft變量最終會跟蹤?個不正確的值:
function withdraw(uint256 _amount) public { require(balances[msg.sender] >= _amount);balances[msg.sender] -= _amount;etherLeft -= _amount;msg.sender.send(_amount); }其他資源:
- 未經檢查的外部寫?
- 掃描“未經檢查 - 發送”錯誤的現場以太坊合同
5.拒絕服務
包括達到gas上限,意外拋出,意外殺死,訪問控制違規
我不??殺了它。 devops199 on the Parity multi-sig wallet
在以太坊的世界中,拒絕服務是致命的:盡管其他類型的應?程序最終可以恢復,但智能合同可以通過 其中?種攻擊永遠脫機。許多??導致拒絕服務,包括在作為交易接受?時惡意?為,?為地增加計算 功能所需的?體,濫?訪問控制訪問智能合約的私?組件,利?混淆和疏忽,...這類攻擊包括許多不同的變體,并可能在未來?年看到很多發展。
損失:估計為514,874 ETH(當時約3億美元)
真實世界影響:
- 政府
- 奇偶校驗多信號錢包
示例:
代碼示例:
在下?的例?中(受以太王的啟發),游戲合同的功能可以讓你成為總統,如果你公開賄賂前?個。不 幸的是,如果前總統是?個聰明的合同,并導致?付逆轉,權?的轉移將失敗,惡意智能合同將永遠保 持總統。聽起來像是對我的獨裁:
function becomePresident() payable {require(msg.value >= price); // must pay the price to become presidentpresident.transfer(price); // we pay the previous presidentpresident = msg.sender; // we crown the new presidentprice = price * 2; // we double the price to become president }在第?個例?中,調?者可以決定下?個函數調?將獎勵誰。由于for循環中有昂貴的指令,攻擊者可 能會引?太?的數字來迭代(由于以太坊中的?體阻塞限制),這將有效地阻?函數的功能。
function selectNextWinners(uint256 _largestWinner) { for(uint256 i = 0; i < largestWinner, i++) { // heavy code}largestWinner = _largestWinner; }其他資源:
- 奇偶Multisig被?客?侵。再次
- 關于Parity multi-sig錢包漏洞和Cappasity令牌眾包的聲明
6.錯誤隨機性
也被稱為 沒有什么是秘密的
合同對block.number年齡沒有?夠的驗證,導致400個ETH輸給?個未知的玩家,他在等待256個街區之前揭示了可預測的中獎號碼。 Arseny Reutov
以太坊的隨機性很難找到。雖然Solidity提供的功能和變量可以訪問明顯難以預測的值,但它們通常要么?看起來更公開,要么受到礦?影響。由于這些隨機性的來源在?定程度上是可預測的,所以惡意?戶通常可以復制它并依靠其不可預知性來攻擊該功能。
損失:超過400 ETH
真實世界影響:
- SmartBillions彩票
- 運?
示例:
代碼示例:
在第?個例?中,a private seed與iteration數字和keccak256散列函數結合使?來確定主叫?是否獲勝。Eventhough的seed是private,它必須是通過交易在某個時間點設置,并因此在blockchain可?。
uint256 private seed; function play() public payable {require(msg.value >= 1 ether);iteration++; uint randomNumber = uint(keccak256(seed + iteration)); if (randomNumber % 2 == 0) {msg.sender.transfer(this.balance); } }在這第?個例?中,block.blockhash正被?來?成?個隨機數。如果將該哈希值blockNumber設置為當前值block.number(出于顯?易?的原因)并且因此設置為,則該哈希值未知0。在blockNumber過去設置為超過256個塊的情況下,它將始終為零。最后,如果它被設置為?個以前的不太舊的區塊號碼,另?個智能合約可以訪問相同的號碼并將游戲合同作為同?交易的?部分進?調?。
function play() public payable { require(msg.value >= 1 ether); if (block.blockhash(blockNumber) % 2 == 0) {msg.sender.transfer(this.balance);} }其他資源: -?在以太坊智能合約中預測隨機數?-?在以太坊隨機
7.前臺運?
也被稱為 檢查時間與使?時間(TOCTOU),競爭條件,事務順序依賴性(TOD)
事實證明,只需要150?左右的Python就可以獲得?個正常運?的算法。 Ivan Bogatyy
由于礦?總是通過代表外部擁有地址(EOA)的代碼獲得燃?費?,因此?戶可以指定更?的費?以便 更快地開展交易。由于以太坊區塊鏈是公開的,每個?都可以看到其他?未決交易的內容。這意味著, 如果某個?戶正在揭示拼圖或其他有價值的秘密的解決?案,惡意?戶可以竊取解決?案并以較?的費 ?復制其交易,以搶占原始解決?案。如果智能合約的開發者不??,這種情況會導致實際的和毀滅性 的前端攻擊。
真實世界影響:
- 班柯
- ERC-20
- 運?
示例:
其他資源:
- 在以太坊智能合約中預測隨機數
- 虛擬和解的前衛,悲痛和危險
- Frontrunning Bancor
8.時間篡改
也被稱為 時間戳依賴
如果?位礦?持有合同的股份,他可以通過為他正在挖掘的礦區選擇合適的時間戳來獲得優勢。 Nicola Atzei,Massimo Bartoletti和Tiziana Cimoli
從鎖定令牌銷售到在特定時間為游戲解鎖資?,合同有時需要依賴當前時間。這通常通過Solidity中的 block.timestamp別名或其別名完成now。但是,這個價值從哪?來?來?礦?!由于交易的礦?在報告采礦發?的時間??具有回旋余地,所以良好的智能合約將避免強烈依賴所宣傳的時間。請注意, block.timestamp有時(錯誤)也會在隨機數的?成中使?,如#6所述。錯誤的隨機性。
真實世界影響:
政府
示例:
代碼示例:
以下功能只接受特定?期之后的呼叫。由于礦?可以影響他們區塊的時間戳(在?定程度上),他們可以嘗試挖掘?個包含他們交易的區塊,并在未來設定?個區塊時間戳。如果?夠接近,它將在?絡上被接受,交易將在任何其他玩家試圖贏得?賽之前給予礦?以太:
function play() public { require(now > 1521763200 && neverPlayed == true);neverPlayed = false;msg.sender.transfer(1500 ether); }其他資源:
- 對以太坊智能合約的攻擊調查
- 在以太坊智能合約中預測隨機數
- 讓智能合約變得更聰明
9.短地址攻擊
也被稱為 涉及?連鎖問題,客戶端漏洞
為令牌傳輸準備數據的服務假定?戶將輸?20字節?的地址,但實際上并未檢查地址的?度。 Pawe?Bylica
短地址攻擊是EVM本身接受不正確填充參數的副作?。攻擊者可以通過使?專?制作的地址來利?這?點,使編碼錯誤的客戶端在將它們包含在事務中之前不正確地對參數進?編碼。這是EVM問題還是客戶問題?是否應該在智能合約中修復?盡管每個?都有不同的觀點,但事實是,這個問題可能會直接影響很多以太?。雖然這個漏洞還沒有被?規模利?,但它很好地證明了客戶和以太坊區塊鏈之間的交互帶來的問題。其他脫鏈問題存在:重要的是以太坊?態系統對特定的javascript前端,瀏覽器插件和公共節點的深度信任。臭名昭著的鏈外利?被?于Coindash ICO的?客在他們的??上修改了公司的以太坊地址,誘騙參與者將ethers發送到攻擊者的地址。
發現時間表: 2017年4?6??如何通過閱讀區塊鏈來找到1000萬美元
真實世界影響:
未知交換(s)
示例:
其他資源:
- ERC20短地址攻擊說明
- 分析ERC20短地址攻擊
- 智能合同短地址攻擊緩解失敗
- 從標記中刪除短地址攻擊檢查
10.未知的 未知物
我們相信更多的安全審計或更多的測試將沒有什么區別。主要問題是評審?員不知道要尋找什么。 Christoph Jentzsch
以太坊仍處于起步階段。?于開發智能合同的主要語?Solidity尚未達到穩定版本,??態系統的?具仍處于試驗階段。?些最具破壞性的智能合約漏洞使每個?都感到驚訝,并且沒有理由相信不會有另?個同樣出乎意料或同樣具有破壞性的漏洞。只要投資者決定將?量資??于復雜?輕微審計的代碼,我們將繼續看到新的發現導致可怕的后果。對智能合約進?正式驗證的?法尚不成熟,但它們似乎有望成為今?搖搖欲墜的現狀。隨著新類型的漏洞不斷被發現,開發?員需要繼續努?,并且需要開發新?具來在壞?之前找到它們。這個前10名可能會迅速發展,直到智能合約開發達到穩定和成熟的狀態。
總結
以上是生活随笔為你收集整理的以太坊智能合约安全 Dasp Top10的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以太坊智能合约 Hexagon 存在溢出
- 下一篇: 【译】Economics of Fees