保护 Solana 生态系统 (4) — 账户验证

保护 Solana 生态系统 (4) — 账户验证

0. 回顾

1. 概述

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

2. 说明

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

3. 账户验证

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

3.1 代码审查 (PrivilegeOwner)

我们首先定义两个结构体: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/2fVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?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
Weekly Web3 Security Incident Roundup | Feb 9 – Feb 15, 2026

Weekly Web3 Security Incident Roundup | Feb 9 – Feb 15, 2026

During the week of February 9 to February 15, 2026, three blockchain security incidents were reported with total losses of ~$657K. All incidents occurred on the BNB Smart Chain and involved flawed business logic in DeFi token contracts. The primary causes included an unchecked balance withdrawal from an intermediary contract that allowed donation-based inflation of a liquidity addition targeted by a sandwich attack, a post-swap deflationary clawback that returned sold tokens to the caller while draining pool reserves to create a repeatable price-manipulation primitive, and a token transfer override that burned tokens directly from a Uniswap V2 pair's balance and force-synced reserves within the same transaction to artificially inflate the token price.

Top 10 "Awesome" Security Incidents in 2025

Top 10 "Awesome" Security Incidents in 2025

To help the community learn from what happened, BlockSec selected ten incidents that stood out most this year. These cases were chosen not only for the scale of loss, but also for the distinct techniques involved, the unexpected twists in execution, and the new or underexplored attack surfaces they revealed.

#10 Panoptic Incident: XOR Linearity Breaks the Position Fingerprint Scheme

#10 Panoptic Incident: XOR Linearity Breaks the Position Fingerprint Scheme

On August 29, 2025, Panoptic disclosed a Cantina bounty finding and confirmed that, with support from Cantina and Seal911, it executed a rescue operation on August 25 to secure roughly $400K in funds. The issue stemmed from a flaw in Panoptic’s position fingerprint calculation algorithm, which could have enabled incorrect position identification and downstream fund risk.