Back to Blog

安全 Solana 生态系统 (4) — 账户验证

April 1, 2022
6 min read

0. 回顾

1. 概述

在上一篇文章 博客 中,我们讨论了如何升级程序。在本文中,我们将介绍访问控制相关的问题,这是 DeFi 领域最常见和最基础的安全主题之一。

2. 说明

在 Solana 中,每个程序都导出一个单独的 entrypoint,它通过 entrypoint! 定义。与以太坊不同,客户端只能调用一个定义为入口点的函数,通常称为 process_instruction。入口点函数接收三个参数:智能合约的程序 ID、程序将操作的账户以及指令数据。指令数据指定要调用的指令。下图展示了一个示例。通过解包指令数据,可以选择不同的指令(例如,Lock、Unlock)。因此,可以从入口点访问的指令对所有人都是公开的,并且可以使用指定的指令数据来执行。

3. 账户验证

如前所述,程序接收其需要读取或写入的账户。这种设计带来了两个问题。对于要读取的账户,如何保证账户中存储的数据是可信的。对于要写入的账户,如何保证只有特权用户才能调用指令写入账户。下面,我们将阐述访问控制问题。所有测试代码都可以在 此处 找到。

3.1 代码审查(特权所有者)

我们首先定义两个结构体:DoorConfig。只有结构体 door 中指定的密钥账户(第 17 行)才能打开创建的 door。但是,当系统状态被锁定(在结构体 Config(第 81 行)中指定)时,门无法被打开。

如前所述,Config 账户指定了门是否可以打开。在这种情况下,程序中应该只有一个 Config 账户。为了实现这一点,我们使用 PDA 来存储 Config 的数据。初始化 Config 账户后,我们将 is_initialized 属性设置为 true,以便攻击者无法再次初始化(第 108 - 110 行)。

指令 Open() 用于打开门。该指令接收多个账户,包括要打开的门账户、config 账户和旨在打开 doorowner 账户。为了保证门属于程序并且配置有效,我们检查 door 账户和 config 账户的所有者(第 204 - 205 行)。这可以防止恶意用户提供虚假账户。这就回答了我们的第一个问题:为了保证要读取的账户是可信的,我们需要检查账户的所有者!请注意,只有 door 账户的所有者才能打开门。在这种情况下,我们检查所有者账户是否是 door 的真实 owner,更重要的是,指令是否由所有者授权(第 217 - 219 行)。

validate_owner() 函数中,我们首先检查这两个账户的公钥是否相同,然后检查所有者的签名。这就回答了第二个问题:为了保证只有特权用户才能调用 open 指令,我们需要检查账户的所有者和签名者。close 指令与 open 类似,详情请参见代码。

我们将程序部署到了测试网,您可以在以下链接中找到它:

https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet

所有测试交易如下所示。此交易的整个过程是 Allocate PDA()-> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close()

https://explorer.solana.com/tx/2X9CyMrHTNEvbzXTE95gem2j8spnvsQsabFeSpV8hiNpYjiQPPzLRqt5KN86ZYRjnQvydvs7y5eUjJK7no8knDhk?cluster=testnet
https://explorer.solana.com/tx/2XfVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?cluster=testnet
https://explorer.solana.com/tx/5Em41sg7yFXeNpnEJnhUQJanfLWKwjMqiBeNAqEEzFrSN9P8zKKafcv5F7RKT2pseB171qeoa8Uz4fKgazzayCnW?cluster=testnet
https://explorer.solana.com/tx/2PMtzpSgjnKDLGmRWBdUSFBPimWnudCPekUYbWzPzokENFYa4N4ab4HCtynfGrzswFPTgGYKHU8PccUMHv3mXHkR?cluster=testnet
https://explorer.solana.com/tx/3kviP9MqkWGMV4yA7k7yPQ5BGfXmcYLcctmY1u2D7n56eT1nx8jMtDumkUNJy8yA3KkmzrmfQLjqpigc8ehGZzBN?cluster=testnet
https://explorer.solana.com/tx/38iEaJBzuGMLbfcszdVB8pkniezH8JrA3XGq7JdADZTQ4hNQC82GSTUA2bmcypdVy3t7htWnUzkZ4F8EakmNvqz8?cluster=testnet

3.2 攻击交易

为了说明所有者检查和签名者检查的重要性,我们举了两个攻击场景作为例子。

第一种场景

第一个场景是“门”的所有者尝试在 config 被锁定时打开门。为此,我们在另一个程序中创建了一个假的 config 账户,并将 is_lock 属性设置为 false。自定义程序的代码如下所示。

我们发送交易来创建假的 config 账户,假的 config 账户的公钥是:2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy。

https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet

一旦创建了假的 config 账户,我们就将其馈送到程序中(第 423 行)。

结果如下所示,日志显示“指令的程序 ID 不正确”,这意味着 config 账户的所有者必须是程序。因此,攻击者无法绕过此检查。

第二种场景

第二种场景是一个恶意用户尝试在门未锁定时打开门。

在这种情况下,我们将真实的所有者账户馈送到程序中(第 419 行)并发送交易。结果如下所示。

它显示“签名验证失败”,这意味着真实的所有者必须签署交易才能打开门,因此我们的第二次攻击也失败了。

4. 总结

在 Solana 中,指令根据客户端或程序提供的不同账户实现指定的逻辑。因此,对账户进行适当的检查非常重要。

在本文中,我们介绍了如何正确检查账户,并使用两个攻击场景来说明这些检查的重要性。请继续关注,我们将分享更多文章。

阅读本系列的更多文章:


关于 BlockSec

BlockSec 是一家开创性的区块链安全公司,由一群全球顶尖的安全专家于 2021 年创立。公司致力于提高新兴 Web3 世界的安全性和可用性,以促进其大规模采用。为此,BlockSec 提供智能合约和 EVM 链 安全审计 服务,用于安全开发和主动阻止威胁的 Phalcon 平台,用于资金追踪和调查的 MetaSleuth 平台,以及用于 Web3 构建者在加密世界高效冲浪的 MetaSuites 扩展。

迄今为止,公司已为 MetaMask、Uniswap Foundation、Compound、Forta 和 PancakeSwap 等 300 多家知名客户提供服务,并在两轮融资中从 Matrix Partners、Vitalbridge Capital 和 Fenbushi Capital 等知名投资者那里获得了数千万美元的投资。

官方网站:https://blocksec.com/ 官方 Twitter 账号:https://twitter.com/BlockSecTeam

Sign up for the latest updates
The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis
Security Insights

The Decentralization Dilemma: Cascading Risk and Emergency Power in the KelpDAO Crisis

This BlockSec deep-dive analyzes the KelpDAO $290M rsETH cross-chain bridge exploit (April 18, 2026), attributed to the Lazarus Group, tracing a causal chain across three layers: how a single-point DVN dependency enabled the attack, how DeFi composability cascaded the damage through Aave V3 lending markets to freeze WETH liquidity exceeding $6.7B across Ethereum, Arbitrum, Base, Mantle, and Linea, and how the crisis forced decentralized governance to exercise centralized emergency powers. The article examines three parameters that shaped the cascade's severity (LTV, pool depth, and cross-chain deployment count) and provides an exclusive technical breakdown of Arbitrum Security Council's forced state transition, an atomic contract upgrade that moved 30,766 ETH without the holder's signature.

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 13 – Apr 19, 2026

This BlockSec weekly security report covers four attack incidents detected between April 13 and April 19, 2026, across multiple chains such as Ethereum, Unichain, Arbitrum, and NEAR, with total estimated losses of approximately $310M. The highlighted incident is the $290M KelpDAO rsETH bridge exploit, where an attacker poisoned the RPC infrastructure of the sole LayerZero DVN to fabricate a cross-chain message, triggering a cascading WETH freeze across five chains and an Arbitrum Security Council forced state transition that raises questions about the actual trust boundaries of decentralized systems. Other incidents include a $242K MMR proof forgery on Hyperbridge, a $1.5M signed integer abuse on Dango, and an $18.4M circular swap path exploit on Rhea Finance's Burrowland protocol.

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026
Security Insights

Weekly Web3 Security Incident Roundup | Apr 6 – Apr 12, 2026

This BlockSec weekly security report covers four DeFi attack incidents detected between April 6 and April 12, 2026, across Linea, BNB Chain, Arbitrum, Optimism, Avalanche, and Base, with total estimated losses of approximately $928.6K. Notable incidents include a $517K approval-related exploit where a user mistakenly approved a permissionless SquidMulticall contract enabling arbitrary external calls, a $193K business logic flaw in the HB token's reward-settlement logic that allowed direct AMM reserve manipulation, a $165.6K exploit in Denaria's perpetual DEX caused by a rounding asymmetry compounded with an unsafe cast, and a $53K access control issue in XBITVault caused by an initialization-dependent check that failed open. The report provides detailed vulnerability analysis and attack transaction breakdowns for each incident.