起因#
看到推友发推文,提及某智能合约中的嚴重漏洞。
流程分析#
攻擊者批量調用合約的 VOTEToken()
函數,實現憑空創建大量 VOTETRUMP
代幣,然後將 VOTETRUMP
代幣通過 Uinswap
兌換為 ETH
,實現套利。
漏洞分析#
正巧最近在參與Solidity 殘酷共學 (DeFiHackLabs x WTF Academy),在課程的第 11 講:構造函數和修飾器有這樣的描述:
注意:構造函數在不同的 Solidity 版本中的語法並不一致,在 Solidity 0.4.22 之前,構造函數不使用 constructor 而是使用與合約名同名的函數作為構造函數而使用,由於這種舊寫法容易使開發者在書寫時發生疏漏(例如合約名叫 Parents,構造函數名寫成 parents),使得構造函數變成普通函數,引發漏洞,所以 0.4.22 版本及之後,採用了全新的 constructor 寫法。
而查看合約代碼可以看到合約使用的 Solidity
版本是 ^0.4.11
,是低於 0.4.22
。 這意味著該合約的構造函數定義遵循舊版規則。
構造函數錯誤:合約名稱為 VeritaseumToken,而實際定義的構造函數名為 VOTEToken。由於二者不一致,VOTEToken 函數並未被識別為構造函數,而是成為了一個普通的公共函數。此外,函數沒有使用任何可見性修飾符,因此任何人都可以隨意調用它,並通過調用該函數將其賬戶的 VOTETRUMP 代幣餘額增加到代幣的最大供應量。
這種設計失誤為攻擊者創造了條件,他們通過調用 VOTEToken () 函數鑄造出大量 VOTETRUMP 代幣,並最終在去中心化交易所中套利。
修復漏洞#
- 升級 Solidity 版本:首先,建議將 Solidity 版本升級至 0.4.22 或更高版本,以使用 constructor 關鍵字定義構造函數。這可以避免由於構造函數名稱拼寫錯誤而引發的漏洞。
- 修正構造函數定義:如果無法升級合約代碼版本,必須確保構造函數名稱與合約名稱一致。在這個案例中,應該將 VOTEToken () 改為 VeritaseumToken ()。
- 添加適當的權限控制:即使使用舊版構造函數定義,仍需為重要函數添加適當的權限控制(如 onlyOwner 修飾器),避免任何用戶可以調用這些函數進行代幣鑄造。
警示#
此漏洞提醒我們,在使用低版本的 Solidity 編寫合約時,必須嚴格遵循構造函數命名規則,避免因為拼寫錯誤引發的嚴重安全問題。同時,對於任何涉及代幣鑄造、轉移等關鍵操作的函數,都應引入權限控制機制,以防止惡意用戶濫用合約漏洞。
此外,在設計合約時,建議使用最新穩定版本的 Solidity,以確保利用新特性和修復已知漏洞,從而提升合約的安全性。