Back to Blog

保障 Solana 生態系統(七)—— 類型混淆

April 29, 2022
4 min read

0. 回顧

1. 概述

在上一篇部落格中,我們介紹了通用多重簽名的實現。在這篇文章中,我們將討論另一個安全議題——類型混淆(Type Confusion)。

2. 反序列化/序列化

在 Solana 中,程式狀態存儲在帳戶中。類型混淆問題發生在帳戶的反序列化/序列化過程中。程式邏輯通常依賴於資料結構,然而,程式在反序列化/序列化過程中可能沒有正確檢查帳戶的類型。這可能會被攻擊者利用,導致意外的損失。

3. 程式碼審查(類型混淆)

以下我們透過一個簡單的程式來說明類型混淆問題。您可以在此處找到測試程式碼。

在測試程式中,我們實現了兩個資料結構,一個是 User,另一個是 Metadata。它們兩者都記錄了一個帳戶(不同的帳戶)的公鑰。

該程式有三個不同的指令。指令 InitializeUser 用於建立 User 帳戶並設定授權帳戶(即 authority)。同樣地,指令 InitializeMeta 用於建立 MetaData 帳戶並設定一個普通帳戶(即 account)。指令 Test 展示了攻擊者如何繞過程式的驗證邏輯,並使用可控制的 MetaData 進行攻擊。

讓我們一步步分析 Test() 指令。程式確保傳入的 User 帳戶擁有者是程式本身(第 86 行 - 第 89 行)。在反序列化後(第 92 行),程式將傳入的 authority 帳戶的公鑰與存儲在 User 帳戶中的公鑰進行比較。如果它們不相等,程式就會回滾(第 93 行 - 第 96 行)。最後的檢查是確保授權帳戶已簽署交易。然而,如果攻擊者傳入受控的 Metadata 帳戶,所有的檢查仍然可以被繞過。原因在於程式沒有檢查帳戶的類型。它接收一串位元組流並直接將其反序列化為程式中定義的不同結構體類型。

我們部署了該測試程式以進行進一步測試,您可以在此連結中找到。

3.1 發送交易

部署程式後,我們編寫腳本按順序呼叫程式中提供的三個指令。

我們首先呼叫 InitializeUserInitializeMeta。請注意,我們將自己的公鑰設定為存儲在 Metadata 帳戶中的 account

test() 函數中,我們將 Metadata 帳戶作為 User 帳戶傳入,並將我們自己的帳戶作為 authority_info 傳入(第 347 行 - 第 348 行)。程式將 MetadataUser 結構體進行反序列化,所有的檢查都可以被繞過。

我們發送交易,您可以在此處找到它。程式返回了成功,這意味著我們成功地透過未檢查的帳戶類型通過了驗證。

4. 總結

在本文中,我們介紹了 Solana 中的類型混淆問題。避免此類問題有很多方法。例如,我們可以在結構體中增加一個屬性來記錄帳戶類型,並且程式在讀取或寫入傳入的帳戶之前,應始終檢查該類型屬性。請持續關注,我們將在未來的文章中分享更多內容。

閱讀本系列的其他文章:


關於 BlockSec

BlockSec 是一家開拓性的區塊鏈安全公司,由一群全球傑出的安全專家於 2021 年創立。公司致力於增強新興 Web3 世界的安全性與可用性,以促進其大規模採用。為此,BlockSec 提供智慧合約與 EVM 鏈的安全審計服務、用於安全開發與主動威脅阻斷的 Phalcon 平台、用於資金追蹤與調查的 MetaSleuth 平台,以及協助 Web3 構建者在加密世界中高效航行的 MetaSuites 擴充功能。

迄今為止,公司已服務超過 300 家知名客戶,例如 MetaMask、Uniswap Foundation、Compound、Forta 以及 PancakeSwap,並從 Matrix Partners、Vitalbridge Capital 和分布式資本(Fenbushi Capital)等頂尖投資者處獲得了兩輪數千萬美元的融資。

官方網站:https://blocksec.com/

官方 Twitter 帳號:https://twitter.com/BlockSecTeam