设计更好的协议内权限结构

本文探讨了如何设计更安全的 Solana 协议链上权限结构,核心理念是根据风险和及时性对管理操作进行分层。文章建议通过建立五个层级的权限体系,确保危险操作(如升级或修改核心参数)需通过多签和延迟执行,而紧急安全操作(如熔断)则保持高效触发,以此降低协议被黑客攻击的风险。

设计更好的协议内权限结构

Drift 攻击之所以成功,是因为多个组件共同促成了它。一个没有超时的薄弱的 2/5 Multisig。硬件钱包上的盲签。允许同时执行异步签名交易的持久化 Nonce。缓慢的响应。而且,一个权限过大的单一管理员(Admin)权限允许编辑安全限制、添加资产并立即更改管理员密钥。

两个权限平面

在 Solana 上,有两个截然不同的权限平面。首先是升级权限upgrade authority):此账户可以将新版本的代码部署到现有地址。撤销此权限会使程序变为不可变。

其次是你的程序在自身状态机中公开的特权指令。列出资产、下架资产、更改风险参数、切换 Oracle 设置、收取费用、更改费用设置、暂停市场、轮换管理员等等。

这些是完全不同的权力,具有完全不同的故障模式,因此几乎不应该以相同的方式进行控制。

在这篇文章中,我们想要探讨协议内的权限平面。Drift 使用了一个配置好的单一协议内管理员权限,该权限能够执行大多数管理任务。这是一个简单的设计,坦率地说非常普遍。然而,虽然简单通常有利于安全,但在这种情况下,这却是一个大问题。攻击者仅通过一条指令就劫持了这个管理员:将权限转移给攻击者。接着,他们能够添加新资产,调整安全限制,然后抽干协议。

现在你可能已经猜到了显而易见的修复方法。我们可以分离管理功能,并根据其风险状况将其分配给不同的权限,同时强制执行超时作为安全控制。这就是简单的核心思想,我们想讨论如何实现这一点。无论你是正在设计一个新协议还是正在审计一个现有协议,这个框架都能为你提供一种系统化的方式来评估和构建管理员权限。

第一步是列举你的管理员指令并评估每一项的风险状况。你可以通过询问两个简单的问题来进行评估:

  1. 如果恶意行为者触发此操作一次会发生什么?
  2. 协议本身可能需要触发此操作的最快速度是多少?

这会给你两个分数:

  • 风险
    • 0: 灾难性的资金损失(恶意程序升级)
    • 1: 重大的资金损失(类似于 Drift)
    • 2: 较小的资金损失、费用、收益,或针对性的/可社会化的损失
    • 3: 可用性损失
    • 4: 低于上述风险
  • 及时性
    • 0: 立即
    • 1: 一小时内
    • 2: 一天内
    • 3: 一周内

现在你将进入真正的设计循环:使操作变得不那么及时且风险更低。 评分只是第一步。在对操作进行评分后,再问两个问题:

  • 我能让这个操作变得不那么及时吗?
  • 我能让这个操作变得风险更低吗?

重复该循环,直到容易回答“是”的选项基本消失。 然而,你该如何让操作变得不那么及时或风险更低呢?

使操作不那么及时的主要方法是添加一个更安全的后备行动。如果你有办法停止协议,升级就不再是紧急响应。如果你可以收紧 Oracle 防护栏或禁用市场,Oracle 源迁移就不再是一个热路径操作。

使操作风险更低的主要方法是约束操作本身。将“设置费用”改为“在硬编码范围内设置费用”。存款费用可能永远不应超过 10%,即便如此也很高。因此,不要只是检查费用参数是否是有效的 BPS 值,还要确保它在合理的范围内!将“收取费用”改为“从专用的收入池划拨到固定的国库”。费用收取是实现方式改变分类的一个绝佳例子:如果划拨权限可以触碰用户抵押品,它基本上就是伪装的国库抽干权限。如果费用被隔离到专用池中,同样的权力就会变成低得多的风险。

另一种降低风险的好方法是将指令拆分为降低风险和增加风险的部分。将“更改最大 Oracle 陈旧度”拆分为独立的“收紧”和“放宽”指令。

一个好的经验法则是:

每一项特权行动都应该是缓慢的或单向的。

如果它是快速的,它应该只能降低风险。

如果它可以移动价值、扩大风险或重新启用系统,它应该是缓慢的。

风险 vs. 及时性风险 vs. 及时性

一个实际的示例矩阵

在划分了大类别之后,按权限级别分组的基准矩阵如下所示:

Vault 层级

操作 风险 及时性 备注
升级代码 0 2 全量代码替换

高风险操作(缓慢、受限、可撤销)

操作 风险 及时性 备注
恢复 / 取消暂停 / 扩大白名单 1 2 可能重新开启漏洞面;可能需要 Vault
激活市场 / 启用抵押、借贷、杠杆 1 3 错误的配置可能导致资不抵债
放宽风险参数 1 3 扩大风险范围
更改 Oracle 源 / 放宽 Oracle 检查 1 2 错误的重新定价风险
更改费用接收方或费用范围 1 3 可能重定向价值或移除安全护栏
最终下架 / 结算过期的市场 2 2 涉及价值移动,但如果存在仅限减仓模式则非紧急情况
在禁用 / 隔离状态下创建市场 4 3 如果尚不可用则是安全的

低风险操作(下行风险受限)

操作 风险 及时性 备注
将费用划拨至固定国库 2 3 假设费用是隔离的
在硬性限制内更改费用参数 2 2 经济损害,但受限

即时守护者(快速,仅限降低风险)

操作 风险 及时性 备注
紧急停止 / 停止资金流动 3 0 如果设计得好,仅影响可用性
进入仅限减仓模式 / 开始下架流程 3 1 限制进一步的风险敞口
收紧风险参数 3 1 更安全的方向,但可能干扰用户
收紧 Oracle 防护栏 / 禁用市场 3 1 宁愿停止也不愿信任错误数据

撤销守护者

操作 风险 及时性 备注
撤销/移除待定或受损的管理员 3 0 紧急遏制

管理员转移(跨层级)

操作 风险 及时性 备注 权限
提议管理员转移 4 3 在接受前无影响 同级或更高层级
接受管理员转移 继承目标角色 2 应该是延迟且可撤销的 目标角色,超时后

这些表格中最重要的一点不是确切的数字。而是形状。危险的和许可性的行动向上漂移到缓慢的、高度受信任的权限中。快速的权限大多消失在狭窄的、单向的安全行动中。

一个适用于大多数协议的基础权限结构

对于大多数 Solana 协议,一个合理的默认设置是五层。

1. Vault 层级

这是最冷、最慢、最受信任的权限。它应该拥有程序升级权限和任何真正的根本性元权力。最高门槛。最长超时。冷的签名环境。独立的笔记本电脑。这是你锁定最严的角色。有关实际的 Multisig 规模指导,请参阅我们的 100 条 Solana 技巧中的第 22-23 条

还有一个实际的要点:升级权限高于每一个协议内管理员。即使你的程序有自己的管理员树,升级权限总是可以发布改变它的新代码。将其视为“破窗”层,而不不仅仅是另一个同行角色。

2. 高风险操作层级

这用于危险但非根本性的状态更改:激活新市场、放宽风险参数、切换 Oracle 源、放宽检查、最终下架结算、更改费用接收方、接受高权限管理员转移以及从紧急状态恢复。

这一层级仍应是缓慢的。它可以具有比 Vault 级升级更短的超时,但它应该保持严格受限且可撤销。

3. 低风险操作层级

这用于下行风险受限的常规操作:将费用从专用收入池划拨到固定国库、受限的费用更改以及其他不涉及用户偿付能力或协议控制的维护操作。

如果一个“低风险”权限可以更改 Oracle、更改接收方或重新启用系统,那么它实际上就不是低风险的。

4. 即时守护者层级

这是快速路径。它应该没有时间锁定且协作负担低得多,但权衡是严格的范围:它应该只能使协议更安全。

这通常意味着如下权力:

  • 触发紧急停止
  • 停止资金流动
  • 将市场置于仅限减仓模式
  • 收紧风险限制
  • 收紧 Oracle 防护栏
  • 撤销待定的队列操作

应该能够恢复协议、放宽限制、切换 Oracle 源、移动国库资金或轮换管理员上台。

这一层级通常应分为两个:

  • 一个用于人工触发紧急干预的手动守护者 Multisig
  • 一个用于确定性停止操作的非常狭窄的自动化热钱包

自动化钱包应该被视为刹车踏板,而不是方向盘。让一个热钥根据预先声明的条件暂停市场或停止资金流动是可以的。但让同一个热钥决定新的 Oracle 源或增加风险参数是不可以的。

5. 撤销守护者

这个角色的存在是为了在队列中或待定的危险操作超时窗口期间中断它们。它对于管理员转移和其他延迟的高风险操作特别有价值。在某些系统中,这可以由与手动守护者相同的签署人担任。在其他系统中,它可以更广泛,因为否决权通常比执行权更容易分发且更安全。

理想的撤销守护者可以阻止坏事,而其自身无法做很多好事。

权限层级权限层级

关于熔断机制

每个协议都应该拥有的一个核心功能是熔断机制或全局程序状态。此状态在入口点进行检查,并可以禁止任何进一步的操作。我们推荐的主要熔断状态只是“正常运行”和“紧急停止直至升级”,但你也可以添加限制协议只能进行子集操作的中间状态。

关键属性是单调性:快速权限只能增加限制,而只有较慢、更受信任的权限才能将其放宽回正常运行状态。

这引出了对一个微妙问题的实际回答:在暂停期间应该允许什么?

答案不是“所有管理操作”。它应该是一个非常小的恢复平面:

  • 更严格的紧急转换
  • 撤销/移除管理员操作
  • 代码升级 / 恢复路径(这本身就是开放的)
  • 如果是明确列入白名单且已知安全的,则可能是非常具体的结算指令

然而,当攻击正在发生时,你无法立即知道漏洞的根本原因。在暂停协议的同时仍允许某些指令,始终保留着这些特定指令直接存在漏洞或以某种方式受到间接影响的风险。

即使是“安全”的结算指令,如果它基于已被其他地方的漏洞破坏的内部账目来计算其操作,也可能产生负面影响。这就是为什么最安全的默认设置是暂停所有操作,直到程序升级。

安全的管理员转移

转移管理员权限是协议可以执行的最敏感的操作之一。被攻破的转移机制正是 Drift 攻击者夺取控制权的方式。安全的模式是带有撤销窗口的两步过程:

  1. 当前管理员提议一个新的管理员地址
  2. 强制性的超时窗口开始
  3. 超时后,新管理员接受该角色
  4. 在超时期间,撤销守护者或当前管理员可以撤销该提案
  5. 独立地,更高权限或撤销守护者可以立即移除受损的管理员,而无需经过提案流程

核心原则:增加权力应该是缓慢的,移除权力应该是快速的。

如果怀疑管理员受损,操作流程应该是显而易见的:

  • 守护者暂停或收紧协议
  • 撤销守护者撤销任何待定的恶意更改
  • 更强权限移除或轮换受损的管理员
  • 仅在审查后恢复,且不能由触发停止的同一个快速角色恢复

潜藏在这一切之下的设计原则

大多数协议需要管理操作才能运行。

目标是确保每一项特权行动都具有最小的爆炸半径最大的响应窗口

这意味着:

  • 将广泛的行动拆分为有方向性的、分阶段的和有范围的行动
  • 尽可能添加价值受限的不变量
  • 添加更安全的后备操作,使危险行动不那么紧迫
  • 保持快速权力是单向的
  • 保持许可性权力是缓慢的
  • 分离停止与恢复
  • 分离收紧与放宽
  • 分离提议与接受
  • 保持升级权限高于并独立于常规管理

如果你反复这样做,权限结构就会自动变得清晰。

错误的问题是:“哪个 Multisig 应该拥有管理员权限?”

正确的问题是:“在我们需要的时间速度内,解决这个问题的最小权力是什么?”

这个问题才是将模糊的“管理员系统”转变为真正的 Solana 权限架构的关键。

如果你正在设计或审查权限结构,审计有助于验证你的设计

  • 原文链接: accretion.xyz/blog/autho...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
accretionxyz
accretionxyz
Solana Audits | Solana Security & Research | Looking for an audit?