Solana 生態安全和審計策略

背景

11 月 14 日至 17 日,Solana Hacker House 在香港舉辦為期四天的線下活動,由 Solana Labs 核心工程師提供現場指導,同時還有來自其他生態系統團隊的導師支援。 慢霧安全團隊的公鏈安全負責人 Johan 受邀在活動中做了一個主題為 Advanced Security and Auditing Strategies for Solana Blockchain 的演講,從開發中的安全考量、Solana 中的安全事件、如何做智能合約安全審計三個方面為大家講解 Solana 生態安全和審計策略。

開發中的安全考量

帳號的公私鑰對

Solana 的 Public key 由 Ed25519 演算法生成,該演算法安全快速,有一定的抗量子計算的能力,且生成的簽名具有確定性,可以更好地抵抗簽名延展性攻擊。

Solana 帳號

Solana 的設計理念和 Linux 的檔有一定的相似性,帳號可以用於存儲數據,也有嚴格的擁有權和讀寫許可權控制。 Linux 通過Path來指向要讀寫或執行的檔,而Solana通過Publickey指向要讀寫或運行的帳號,不同的是Solana帳號需要為存儲空間支付費用。

Solana 帳號具有以下特性:

  • 帳號是用於存儲數據的
  • 帳號的最大存儲空間是 10 MB
  • 儲存空間需要支付租金
  • 預設建立帳號時的 owner 是 Program
  • Programs 是儲存在帳號中的可執行程式
  • Programs 可由使用者和其它 Programs 調用
  • Programs 是無狀態的
  • PDA 帳號最大存儲空間是 10 KB

程序帳號 & 數據帳號

由於 Solana 的 Programs 是無狀態的,因此它在存儲數據的時候就需要創建用於存儲數據的帳號,即 PDA 帳號,PDA 帳號的 owner 可以將數據以特定的結構序列化後存儲在 Data Account 裡。

程序指令

下圖是 Solana 智慧合約的調用示意圖,和乙太坊的智慧合約不同的是,Solana 一個 Transaction 里可以通過 Instruction 調用多個 Program。 用戶端調用 Program 時,首先需要傳入幾個關鍵參數(Program ID, Accounts, Data) 來構造 Instruction,這個調用非常簡單靈活,但也因此存在非常多的安全引患。

帳號的校驗就是其中一個嚴重的安全隱患,智能合約需要非常嚴謹地設計賬號的關聯關係,我們看下圖的結構,key 指向帳號本身,lamports 需要校驗租金是否足夠,data 要根據特定場景解析出具體的值進行校驗,owner 通常與 Program ID 相關聯,還有要校驗簽名、帳號是否可寫等等。

程序運行時的約束

程序在運行時受到 runtime 的約束,例如:

  • 只有帳號的所有者才能更改擁有者
  • 未分配給 Program 的帳號不能減少其餘額
  • 唯讀和可執行帳號的餘額可能不會更改
  • 只有擁有者可以更改帳號大小和資料
  • 帳號被添加可執行屬性以後就無法回退
  • 任何人都無法修改與帳號相關聯的 rent_epoch

重入保護

這是 runtime 對智慧合約的調用做的另一個限制。 在乙太坊創建早期,發生過一起知名的重入攻擊事件,導致大量投資人的資金被盜,Solana 吸取了這個教訓,禁止了合約的重入。

帳號安全編碼注意事項

  • **Key 校驗:**檢測傳入的帳戶是否是預期的帳戶,例如 Sys 帳戶
  • **Owner 校驗:**驗證數據編寫者是否具有適當的授權
  • **Signer 校驗:**認證發起請求的調用者的身份
  • **Program ID 校驗:**確認執行環境是否符合預期條件
  • **PDA 校驗:**驗證數據完整性,以確認其來自可信任的來源
  • **Lamports 校驗:**檢測用於存儲數據的租金的充足性
  • **Data 校驗:**分析數據格式,以確保符合預期結構,比如驗證 SPL-Token 規範

Solana 上的資產:代幣

由於 programs 是無狀態的,所以 token 並不能只在單個賬號中實現,token 主要由這幾部分組成,token-program, mint-account 和 token-account。 簡單地說,發行一個 token,就是創建了一個 mint-account,接收一個新的代幣,就是創建了一個 token-account。

mint-account 中存儲了基本的代幣資訊,比如 mint-authority, supply, decimals, is_initialized, freeze-authority。

token-account 中記錄了使用者持有的代幣資訊,比如 mint, owner, amount 等,還有賬號的授權資訊,如 delegate, delegate_amount 等。

下圖是代幣各帳號之間的關係圖,token-program 可以無限地創建代幣,使用者也可以擁有無限的 token-account,他們的 account owner 都是 token-program。

NFT 也一種SPL-token,目前預設使用的是 metaplex 創建的標準。 相比同質化代幣,NFT 的主要特點是它的 supply 為 1,decimals 為 0,代表 NFT 獨一無二且不可分割。

值得一提的是,token 的授權模型中一次只允許授權給一個帳號,相比 ERC-20 標準,這種方式大大降低了代幣被盜的風險。

以下是 SPL-token 在程式設計中需要注意的事項:

  • **Token Program ID 校驗:**確認代幣是由官方項目發行的
  • **Mint 校驗:**確保收到的是正確的代幣
  • **Mint Authority 校驗:**保護代幣鑄造權利,利用如多重簽名等方法以防止私鑰濫用
  • **Decimal 校驗:**驗證代幣的小數精度,以確保準確的交易
  • **Amount 校驗:**實施範圍驗證,以防止溢出並保持計算準確性
  • **Freeze Authority 校驗:**確保 NFT 的發行許可權被不可逆地終止

Solana 中的安全事件

據慢霧區塊鏈被黑檔案庫( 統計,截至目前,Solana 生態中的損失已超過 5 億美元。

接下來我們簡單介紹一些Solana中發生過的駭客攻擊事件,讓大家瞭解駭客是如何攻擊Solana應用的。

1.Wormhole 跨鏈橋被攻擊

這個事故的主要原因是傳入的一個系統帳號沒有校驗,駭客使用偽造的帳號,使用精心構造的數據填充帳號,使得智慧合約錯誤地給駭客增發了代幣,此次事件造成了 12 萬個 ETH 的損失。

2. Nirvana 遭閃電貸攻擊

該項目沒有開源,只能從瀏覽器進行分析,我們可以看到駭客從 solend 裡借出了大量的 USDC,操控了代幣的價格,進而獲利 300 多萬美元。 由此可見,並不是專案不開源就不會被駭客攻擊,有經驗、有耐心的攻擊者還是可以分析出協定中可能存在的安全漏洞,因此開發團隊不能有僥倖心理。

3. 大規模盜取私鑰的事件

2022 年 8 月,我們發現 Solana 社區有大量的使用者被盜取私鑰,奇怪的是調查發現他們使用的並不是同一個錢包,而且使用習慣也不相同,所以該事件的原因並沒有定論。 但是我們發現有一些錢包由於使用了sentry元件,導致私鑰被上傳到服務端。 慢霧安全團隊曾寫過慢霧:Solana 公鏈大規模盜幣事件的分析,感興趣的朋友可以點擊查看。

4. 代幣假充值攻擊

這是一個鏈下的安全問題,攻擊者創建一個 token-account,往這個帳號里轉移代幣,然後轉出,最後把這個 token-account 的 owner 轉移給交易所的充值位址,交易所在檢測 token-account 的鏈上記錄時,會誤認為這個帳號有真實的充值,於是為這個惡意使用者進行充值,導致了攻擊的發生。

如何做智能合約安全審計

安全並不是只有在技術上做好就行,因為安全的環境在經過時間的變化后可能會有新的變數引入,這些變化導致系統變得脆弱。 我們認為做好安全需要考慮三個重要因素:要有安全預算、要進行持續的審計、要有高管直接負責安全工作。

智慧合約安全審計是一個嚴謹過程,所需要掌握的知識和技能也很多,慢霧安全團隊在 Github 上開放了智慧合約安全審計技能樹( 和 Solana 智慧合約安全最佳實踐(歡迎感興趣的朋友移步到 Github 上閱讀。

結語

慢霧安全團隊在智慧合約安全審計領域里耕耘多年,Badwhale 是慢霧安全團隊獨家且沉澱多年的商業系統,為數十個平台持續服務多年,已避免了預估幾十億美金資產的假充值風險,也支援 Solana 的假充值檢測。 目前,慢霧安全團隊已審計過數十個 Solana 的專案,如果專案方有審計方面的需求,歡迎與我們聯繫。

最後,感謝 Solana Hacker House 的邀請,希望通過本次分享説明大家更好地認識了 Solana 的生態安全和審計策略。

查看原文
此頁面可能包含第三方內容,僅供參考(非陳述或保證),不應被視為 Gate 認可其觀點表述,也不得被視為財務或專業建議。詳見聲明
  • 讚賞
  • 留言
  • 轉發
  • 分享
留言
0/400
暫無留言
交易,隨時隨地
qrCode
掃碼下載 Gate App
社群列表
繁體中文
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)