'成都鏈安漏洞分析連載第十五期:合約編寫規範'

""成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

成都鏈安漏洞分析連載第十五期:合約編寫規範"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

成都鏈安漏洞分析連載第十五期:合約編寫規範成都鏈安漏洞分析連載第十五期:合約編寫規範

5. 以太坊最新安全規範

Solidity

0.4.22以及以上的編譯器版本,構造函數建議聲明方式:constructor public {}

Solidity 0.4.21以及以上的編譯器版本,觸發事件建議採用:emit Transfer

6. 對編譯器版本的說明

建議固定編譯器版本,即pragma solidity 0.4.8,然後使用對應編譯器版本編譯發佈合約。固定編譯器版本有助於確保合約不會被用於最新的可能還有bug未被發現的編譯器去部署。智能合約也可能會由他人部署,而pragma標明瞭合約作者希望使用哪個版本的編譯器來部署合約。

7. 棄用項

Solidity處於不斷的更新迭代中,在此過程存在部分表達式棄用,開發者不應在棄用之後的版本使用它們。

suicide 在0.4.3版本已棄用,使用selfdestruct 替代

callcode在0.4.12版本已棄用

throw在0.4.13版本已棄用,使用revert替代

sha3在0.4.17版本會彈出已棄用警告,使用keccak256 替代

var在0.4.20版本已棄用

msg.gas在0.4.22已棄用,使用gasleft替代

constant 作為函數狀態修飾符在0.4.24已棄用,使用view代替years在0.4.24已 棄用

8. 誤用assert、require、revert、throw

Solidity官方對assert、require、revert、throw的介紹如下:

Solidity 使用狀態恢復異常來處理錯誤。這種異常將撤消對當前調用(及其所有子調用)中的狀態所做的所有更改,並且還向調用者標記錯誤。 函數 assert 和 require 可用於檢查條件並在條件不滿足時拋出異常。assert 函數只能用於測試內部錯誤,並檢查非變量。 require 函數用於確認條件有效性,例如輸入變量,或合約狀態變量是否滿足條件,或驗證外部合約調用返回的值。 如果使用得當,分析工具可以評估你的合約,並標示出那些會使 assert 失敗的條件和函數調用。 正常工作的代碼不會導致一個 assert 語句的失敗;如果這發生了,那就說明出現了一個需要你修復的 bug。

還有另外兩種觸發異常的方法:revert 函數可以用來標記錯誤並恢復當前的調用。 revert 調用中包含有關錯誤的詳細信息是可能的,這個消息會被返回給調用者。已經不推薦的關鍵字 throw 也可以用來替代 revert (但無法返回錯誤消息)。

在內部, Solidity 對一個 require 式的異常執行回退操作(指令 0xfd )並執行一個無效操作(指令 0xfe )來引發 assert 式異常。 在這兩種情況下,都會導致 EVM 回退對狀態所做的所有更改。回退的原因是不能繼續安全地執行,因為沒有實現預期的效果。 因為我們想保留交易的原子性,所以最安全的做法是回退所有更改並使整個交易(或至少是調用)不產生效果。 請注意, assert 式異常消耗了所有可用的調用 gas ,而從Metropolis 版本起 require 式的異常不會消耗任何 gas。

適合使用Require的場景:

1) 驗證用戶輸入:require(_to != address(0));

2) 驗證外部合約返回值:require(external.send(amount)) ;

3) 驗證執行代碼的前提條件:require(allowed[_from][msg.sender] >= _value);

4) require應該經常使用

5) require一般位於函數的開頭處

適合用assert的場景:

1) 溢出檢查:c=a+b;assert(c>=a);

2) 檢查常數:assert(this.balance >= totalBalance)

3) 執行操作後驗證狀態

4) 避免絕對不應該出現的狀況

5) assert不應經常使用(觸發異常會消耗所有gas)

6) assert一般位於函數結尾處

revert和require類似,可以用於複雜邏輯的場景,throw已棄用。

9. SafeMath使用建議

為了避免開發人員忽略對溢出的檢查,建議使用SafeMath。

下面是OpenZeppelin編寫的SafeMath庫

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

成都鏈安漏洞分析連載第十五期:合約編寫規範成都鏈安漏洞分析連載第十五期:合約編寫規範

5. 以太坊最新安全規範

Solidity

0.4.22以及以上的編譯器版本,構造函數建議聲明方式:constructor public {}

Solidity 0.4.21以及以上的編譯器版本,觸發事件建議採用:emit Transfer

6. 對編譯器版本的說明

建議固定編譯器版本,即pragma solidity 0.4.8,然後使用對應編譯器版本編譯發佈合約。固定編譯器版本有助於確保合約不會被用於最新的可能還有bug未被發現的編譯器去部署。智能合約也可能會由他人部署,而pragma標明瞭合約作者希望使用哪個版本的編譯器來部署合約。

7. 棄用項

Solidity處於不斷的更新迭代中,在此過程存在部分表達式棄用,開發者不應在棄用之後的版本使用它們。

suicide 在0.4.3版本已棄用,使用selfdestruct 替代

callcode在0.4.12版本已棄用

throw在0.4.13版本已棄用,使用revert替代

sha3在0.4.17版本會彈出已棄用警告,使用keccak256 替代

var在0.4.20版本已棄用

msg.gas在0.4.22已棄用,使用gasleft替代

constant 作為函數狀態修飾符在0.4.24已棄用,使用view代替years在0.4.24已 棄用

8. 誤用assert、require、revert、throw

Solidity官方對assert、require、revert、throw的介紹如下:

Solidity 使用狀態恢復異常來處理錯誤。這種異常將撤消對當前調用(及其所有子調用)中的狀態所做的所有更改,並且還向調用者標記錯誤。 函數 assert 和 require 可用於檢查條件並在條件不滿足時拋出異常。assert 函數只能用於測試內部錯誤,並檢查非變量。 require 函數用於確認條件有效性,例如輸入變量,或合約狀態變量是否滿足條件,或驗證外部合約調用返回的值。 如果使用得當,分析工具可以評估你的合約,並標示出那些會使 assert 失敗的條件和函數調用。 正常工作的代碼不會導致一個 assert 語句的失敗;如果這發生了,那就說明出現了一個需要你修復的 bug。

還有另外兩種觸發異常的方法:revert 函數可以用來標記錯誤並恢復當前的調用。 revert 調用中包含有關錯誤的詳細信息是可能的,這個消息會被返回給調用者。已經不推薦的關鍵字 throw 也可以用來替代 revert (但無法返回錯誤消息)。

在內部, Solidity 對一個 require 式的異常執行回退操作(指令 0xfd )並執行一個無效操作(指令 0xfe )來引發 assert 式異常。 在這兩種情況下,都會導致 EVM 回退對狀態所做的所有更改。回退的原因是不能繼續安全地執行,因為沒有實現預期的效果。 因為我們想保留交易的原子性,所以最安全的做法是回退所有更改並使整個交易(或至少是調用)不產生效果。 請注意, assert 式異常消耗了所有可用的調用 gas ,而從Metropolis 版本起 require 式的異常不會消耗任何 gas。

適合使用Require的場景:

1) 驗證用戶輸入:require(_to != address(0));

2) 驗證外部合約返回值:require(external.send(amount)) ;

3) 驗證執行代碼的前提條件:require(allowed[_from][msg.sender] >= _value);

4) require應該經常使用

5) require一般位於函數的開頭處

適合用assert的場景:

1) 溢出檢查:c=a+b;assert(c>=a);

2) 檢查常數:assert(this.balance >= totalBalance)

3) 執行操作後驗證狀態

4) 避免絕對不應該出現的狀況

5) assert不應經常使用(觸發異常會消耗所有gas)

6) assert一般位於函數結尾處

revert和require類似,可以用於複雜邏輯的場景,throw已棄用。

9. SafeMath使用建議

為了避免開發人員忽略對溢出的檢查,建議使用SafeMath。

下面是OpenZeppelin編寫的SafeMath庫

成都鏈安漏洞分析連載第十五期:合約編寫規範

在合約中使用SafeMath示例

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

成都鏈安漏洞分析連載第十五期:合約編寫規範成都鏈安漏洞分析連載第十五期:合約編寫規範

5. 以太坊最新安全規範

Solidity

0.4.22以及以上的編譯器版本,構造函數建議聲明方式:constructor public {}

Solidity 0.4.21以及以上的編譯器版本,觸發事件建議採用:emit Transfer

6. 對編譯器版本的說明

建議固定編譯器版本,即pragma solidity 0.4.8,然後使用對應編譯器版本編譯發佈合約。固定編譯器版本有助於確保合約不會被用於最新的可能還有bug未被發現的編譯器去部署。智能合約也可能會由他人部署,而pragma標明瞭合約作者希望使用哪個版本的編譯器來部署合約。

7. 棄用項

Solidity處於不斷的更新迭代中,在此過程存在部分表達式棄用,開發者不應在棄用之後的版本使用它們。

suicide 在0.4.3版本已棄用,使用selfdestruct 替代

callcode在0.4.12版本已棄用

throw在0.4.13版本已棄用,使用revert替代

sha3在0.4.17版本會彈出已棄用警告,使用keccak256 替代

var在0.4.20版本已棄用

msg.gas在0.4.22已棄用,使用gasleft替代

constant 作為函數狀態修飾符在0.4.24已棄用,使用view代替years在0.4.24已 棄用

8. 誤用assert、require、revert、throw

Solidity官方對assert、require、revert、throw的介紹如下:

Solidity 使用狀態恢復異常來處理錯誤。這種異常將撤消對當前調用(及其所有子調用)中的狀態所做的所有更改,並且還向調用者標記錯誤。 函數 assert 和 require 可用於檢查條件並在條件不滿足時拋出異常。assert 函數只能用於測試內部錯誤,並檢查非變量。 require 函數用於確認條件有效性,例如輸入變量,或合約狀態變量是否滿足條件,或驗證外部合約調用返回的值。 如果使用得當,分析工具可以評估你的合約,並標示出那些會使 assert 失敗的條件和函數調用。 正常工作的代碼不會導致一個 assert 語句的失敗;如果這發生了,那就說明出現了一個需要你修復的 bug。

還有另外兩種觸發異常的方法:revert 函數可以用來標記錯誤並恢復當前的調用。 revert 調用中包含有關錯誤的詳細信息是可能的,這個消息會被返回給調用者。已經不推薦的關鍵字 throw 也可以用來替代 revert (但無法返回錯誤消息)。

在內部, Solidity 對一個 require 式的異常執行回退操作(指令 0xfd )並執行一個無效操作(指令 0xfe )來引發 assert 式異常。 在這兩種情況下,都會導致 EVM 回退對狀態所做的所有更改。回退的原因是不能繼續安全地執行,因為沒有實現預期的效果。 因為我們想保留交易的原子性,所以最安全的做法是回退所有更改並使整個交易(或至少是調用)不產生效果。 請注意, assert 式異常消耗了所有可用的調用 gas ,而從Metropolis 版本起 require 式的異常不會消耗任何 gas。

適合使用Require的場景:

1) 驗證用戶輸入:require(_to != address(0));

2) 驗證外部合約返回值:require(external.send(amount)) ;

3) 驗證執行代碼的前提條件:require(allowed[_from][msg.sender] >= _value);

4) require應該經常使用

5) require一般位於函數的開頭處

適合用assert的場景:

1) 溢出檢查:c=a+b;assert(c>=a);

2) 檢查常數:assert(this.balance >= totalBalance)

3) 執行操作後驗證狀態

4) 避免絕對不應該出現的狀況

5) assert不應經常使用(觸發異常會消耗所有gas)

6) assert一般位於函數結尾處

revert和require類似,可以用於複雜邏輯的場景,throw已棄用。

9. SafeMath使用建議

為了避免開發人員忽略對溢出的檢查,建議使用SafeMath。

下面是OpenZeppelin編寫的SafeMath庫

成都鏈安漏洞分析連載第十五期:合約編寫規範

在合約中使用SafeMath示例

成都鏈安漏洞分析連載第十五期:合約編寫規範

安全開發 穩步發展

至此,我們已經完成了對以太坊智能合約重點漏洞分析和修復的整合,總的來說,以太坊作為區塊鏈項目火遍全球的起飛平臺,為智能合約概念的實現和區塊鏈技術的普及做出了巨大的貢獻。但是安全問題在發展迅速、市場不夠冷靜的前提下層出不窮,與財產緊密掛鉤的以太坊加密貨幣因為這些問題白白流失,令整個行業人心惶惶。普及安全知識,倡導安全開發與審計,是我們展開漏洞分析連載的初衷。這一期的合約編寫規範為以太坊漏洞分析做了一個小結,希望能幫助更多的開發者重視開發的過程中的問題,關注以太坊社區動向,做好項目部署上鍊前的安全審計,讓整個區塊鏈生態進入發展與安全交融的良性循環。

"成都鏈安漏洞分析連載第十五期:合約編寫規範

合約規範問題皮一下後果很嚴重|成都鏈安漏洞分析連載第十五期 —— 合約編寫規範

針對區塊鏈安全問題,成都鏈安科技團隊每一週都將出智能合約安全漏洞解析連載,希望能幫助程序員寫出更加安全牢固的合約,防患於未然。

引子:以戒為基,止觀相踵。大矩崇規,鏈金烹礦。——《頭陀贊》 宋·黃庭堅

前情提要

上回說到,可見修飾字斟句酌,函數調用約法三章

區塊鏈技術的發展要與安全掛鉤,齊頭並進,讓迅速的發展約束在可靠的範圍之內,才能真正讓新科技穩步推廣,深入人心。在合約開發的過程中,正確精準的添加可見性說明符以及函數修飾符,讓相關函數在可控的範圍之內最大地發揮效用,是安全開發中控制理念的核心。將細微之處,尤其是敏感和重要函數的調用控制做到最嚴謹,可以避免許多導致資金流失、權限被盜的安全隱患。

本期話題

官方標準用心良苦,編寫合規不容小覷

秋去冬來令又更,蕭蕭風籟助清吟。

成都鏈安漏洞分析連載第十五期:合約編寫規範

我們在以太坊智能合約漏洞分析已經走過了14期,將以太坊自興起以來發生的大大小小的攻擊事件以及漏洞發現進行了歸類的分析和討論。從數據類型到變量,從重要函數到代碼邏輯,從代幣合約到區塊鏈遊戲,安全漏洞不僅僅產生於開發過程中的失誤,其源頭在一定程度上來源於開發者安全意識的淡薄。同時,這也體現了區塊鏈行業目前的一個痛點,許多開發者在合約編寫的過程中並沒有注意相應的安全規範,或者並不明確相應的函數和功能實現中官方給出的標準。

這期我們針對官方給出的標準協議和編寫規範,補充相應的安全檢查,旨在將安全在具體的代碼層面體現得淋漓盡致。

成都鏈安漏洞分析連載第十五期:合約編寫規範

知識鋪墊

什麼是以太坊代幣接口標準?

ERC,是Ethereum Request for Comments的縮寫,字面意思是以太坊註釋請求,其本身是一個包含結構化信息的網絡文檔。ERC標準由以太坊社區定義,目的是制定用戶和以太坊交互的規則。這個標準不是一層不變的,社區開發者可以向官方提出自己定義的新標準,但是這個新標準需要被整個以太坊社區接受採納才能應用在以太坊網絡上。從以太坊誕生以來,被採納並且要求代幣遵守的標準出現了幾種:ERC-20,ERC-223,ERC-621,ERC-721,ERC-827。在這些標準的建議下,開發者需要對類型、可見性、返回值、事件、變量與函數命名等方面實現與接口的兼容,也就是按照建議去書寫代碼。從ERC-20啟動了區塊鏈代幣項目的繁榮開始,之後的標準都是在其基礎上進行進一步的補充和完善,便於開發者按照項目需求實現相關的功能。

為了實現安全功能的附加代碼

自從臭名昭著的The DAO事件發生後,以太坊社區開始重視合約的安全問題,並且許多開發者和研究者想要合力解決和防範類似的攻擊事件,於是自發的開始研究代碼編寫過程中可以調整和完善的地方。於是接踵而來的一次又一次安全事件催生了各種附加安全檢查代碼,比較著名的是針對BEC事件中整型溢出漏洞出現的SafeMath代碼庫,開發者可以在編寫過程中使用現成的代碼來實現安全防護,很好的幫助消除了惡性漏洞帶來的影響。

不怕知識不全,就怕視而不見

這些接口標準和安全代碼庫都是為了幫助項目方保障項目的長久穩健運行而設計的。可以說,以太坊社區已經並仍在用民主和科學的方式建立一個行業規範。即便如此,仍有很多開發者在編寫合約,實現項目功能的過程中,選擇坐井觀天,對於安全規範的日新月異疏於關注和學習。這樣一來,開發出來的合約就缺失相關的安全檢查,甚至出現完全與接口不兼容的問題,直接導致的後果就是漏洞被攻擊者利用,項目上鍊就胎死腹中。下面我們就對目前出現的比較重要的編寫規範和建議進行分類討論。

成都鏈安漏洞分析連載第十五期:合約編寫規範

合約編寫規範建議

1. ERC20接口標準檢查

最新的ERC20接口規範如下,建議代幣合約開發者按照以下接口規範進行實現,包括類型、可見性、返回值、事件、變量與函數命名等。

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果代幣合約的開發者未完全按照ERC20標準進行實現,那麼將會對去中心化交易所(DEX)和使用ERC20 Token開發的DAPP產生如下影響:

1) transfer、transferFrom、approve函數未聲明返回值,:

- 合約無法正常完成交易與轉賬

- 部分由合約管理的Token可能永遠被鎖定在合約中

2) transfer、transferFrom、approve操作未觸發Transfer或者Approval事件:

- 目前區塊鏈瀏覽器(eg:etherscan)通過監控事件記錄交易,如果該交易未觸發事件,區塊鏈瀏覽器將無法準確記錄代幣交易

3) name/symbol/decimals使用其他寫法,例如全部大寫(NAME/SYMBOL/DECIMALS):

- 使用ERC20 標準的DAPP(eg:METAMASK)將無法讀取這3個變量的對應值

2. transfer/transferFrom執行失敗未拋出異常導致假充值

某些交易所確認機制不完善以及相關合約代碼未能嚴格遵循標準而引發的問題,攻擊者可實現假充值,情況分析如下:

以ERC-20 Token為例,某些交易所可能僅依賴交易狀態(TxReceiptStatus)和鏈上確認次數(Block Confirmation Number)對交易結果作判斷,忽略了對Token balance的檢查。以下列代碼為例:

成都鏈安漏洞分析連載第十五期:合約編寫規範

如果發起者賬戶為0且_value為大於0的某個值,那麼調用後函數會返回false,但該筆交易的交易狀態是Success:

成都鏈安漏洞分析連載第十五期:合約編寫規範

有問題的交易所在確認轉賬狀態時,如前所述只讀取交易狀態和鏈上確認次數,就會承認該筆轉賬,導致虛假轉賬問題的產生。

合約代碼也存在一定問題,以上述代碼為例,按照ERC-20的標準,transfer、transferFrom函數在Token賬戶轉賬額度不足的條件下應該拋出異常:

成都鏈安漏洞分析連載第十五期:合約編寫規範

正確的代碼應該是

成都鏈安漏洞分析連載第十五期:合約編寫規範

這樣交易狀態自然會變為Fail。換言之,即便交易所依賴交易狀態做最終確認,也可確保自身安然無虞。

3. 目標地址非零檢查

在transfer、transferFrom、transferOwnership

等敏感函數中,用戶操作不可逆,所有建議開發者在這些函數實現中增加目標地址非零檢查:

4. Pausable模塊繼承

建議主合約繼承Pausable Ownable ERC20

標準模塊,當出現重大異常時可以暫停所有交易

成都鏈安漏洞分析連載第十五期:合約編寫規範成都鏈安漏洞分析連載第十五期:合約編寫規範

5. 以太坊最新安全規範

Solidity

0.4.22以及以上的編譯器版本,構造函數建議聲明方式:constructor public {}

Solidity 0.4.21以及以上的編譯器版本,觸發事件建議採用:emit Transfer

6. 對編譯器版本的說明

建議固定編譯器版本,即pragma solidity 0.4.8,然後使用對應編譯器版本編譯發佈合約。固定編譯器版本有助於確保合約不會被用於最新的可能還有bug未被發現的編譯器去部署。智能合約也可能會由他人部署,而pragma標明瞭合約作者希望使用哪個版本的編譯器來部署合約。

7. 棄用項

Solidity處於不斷的更新迭代中,在此過程存在部分表達式棄用,開發者不應在棄用之後的版本使用它們。

suicide 在0.4.3版本已棄用,使用selfdestruct 替代

callcode在0.4.12版本已棄用

throw在0.4.13版本已棄用,使用revert替代

sha3在0.4.17版本會彈出已棄用警告,使用keccak256 替代

var在0.4.20版本已棄用

msg.gas在0.4.22已棄用,使用gasleft替代

constant 作為函數狀態修飾符在0.4.24已棄用,使用view代替years在0.4.24已 棄用

8. 誤用assert、require、revert、throw

Solidity官方對assert、require、revert、throw的介紹如下:

Solidity 使用狀態恢復異常來處理錯誤。這種異常將撤消對當前調用(及其所有子調用)中的狀態所做的所有更改,並且還向調用者標記錯誤。 函數 assert 和 require 可用於檢查條件並在條件不滿足時拋出異常。assert 函數只能用於測試內部錯誤,並檢查非變量。 require 函數用於確認條件有效性,例如輸入變量,或合約狀態變量是否滿足條件,或驗證外部合約調用返回的值。 如果使用得當,分析工具可以評估你的合約,並標示出那些會使 assert 失敗的條件和函數調用。 正常工作的代碼不會導致一個 assert 語句的失敗;如果這發生了,那就說明出現了一個需要你修復的 bug。

還有另外兩種觸發異常的方法:revert 函數可以用來標記錯誤並恢復當前的調用。 revert 調用中包含有關錯誤的詳細信息是可能的,這個消息會被返回給調用者。已經不推薦的關鍵字 throw 也可以用來替代 revert (但無法返回錯誤消息)。

在內部, Solidity 對一個 require 式的異常執行回退操作(指令 0xfd )並執行一個無效操作(指令 0xfe )來引發 assert 式異常。 在這兩種情況下,都會導致 EVM 回退對狀態所做的所有更改。回退的原因是不能繼續安全地執行,因為沒有實現預期的效果。 因為我們想保留交易的原子性,所以最安全的做法是回退所有更改並使整個交易(或至少是調用)不產生效果。 請注意, assert 式異常消耗了所有可用的調用 gas ,而從Metropolis 版本起 require 式的異常不會消耗任何 gas。

適合使用Require的場景:

1) 驗證用戶輸入:require(_to != address(0));

2) 驗證外部合約返回值:require(external.send(amount)) ;

3) 驗證執行代碼的前提條件:require(allowed[_from][msg.sender] >= _value);

4) require應該經常使用

5) require一般位於函數的開頭處

適合用assert的場景:

1) 溢出檢查:c=a+b;assert(c>=a);

2) 檢查常數:assert(this.balance >= totalBalance)

3) 執行操作後驗證狀態

4) 避免絕對不應該出現的狀況

5) assert不應經常使用(觸發異常會消耗所有gas)

6) assert一般位於函數結尾處

revert和require類似,可以用於複雜邏輯的場景,throw已棄用。

9. SafeMath使用建議

為了避免開發人員忽略對溢出的檢查,建議使用SafeMath。

下面是OpenZeppelin編寫的SafeMath庫

成都鏈安漏洞分析連載第十五期:合約編寫規範

在合約中使用SafeMath示例

成都鏈安漏洞分析連載第十五期:合約編寫規範

安全開發 穩步發展

至此,我們已經完成了對以太坊智能合約重點漏洞分析和修復的整合,總的來說,以太坊作為區塊鏈項目火遍全球的起飛平臺,為智能合約概念的實現和區塊鏈技術的普及做出了巨大的貢獻。但是安全問題在發展迅速、市場不夠冷靜的前提下層出不窮,與財產緊密掛鉤的以太坊加密貨幣因為這些問題白白流失,令整個行業人心惶惶。普及安全知識,倡導安全開發與審計,是我們展開漏洞分析連載的初衷。這一期的合約編寫規範為以太坊漏洞分析做了一個小結,希望能幫助更多的開發者重視開發的過程中的問題,關注以太坊社區動向,做好項目部署上鍊前的安全審計,讓整個區塊鏈生態進入發展與安全交融的良性循環。

成都鏈安漏洞分析連載第十五期:合約編寫規範

引用

[1]: https://www.jianshu.com/

[2]: https://mp.weixin.qq.com/

[3]: https://mp.weixin.qq.com/

[4]: https://github.com/

[5]: https://solidity.readthedocs.io/

[6]: https://medium.com/

[7]: https://github.com/

[8]: https://github.com/

"

相關推薦

推薦中...