文章分析了当前区块链安全领域中,私钥泄露已成为最主要的攻击手段,并提出了一个访问控制成熟度模型,从单一EOA控制到完全不可变的架构,为开发者提供了设计更安全、更能容忍私钥泄露的系统的指导,建议开发者尽早关注架构设计,采用多重签名、时间锁、最小权限原则等方法来提高系统的安全性。
“找到所有的 bug!”
这是集结号,大多数协议在部署智能合约之前采取的主要方法,旨在确保其安全性。团队大量投资于审计、竞赛(contests)、模糊测试(fuzzing)和形式化验证,所有这些都旨在检测每一个漏洞。但如果我告诉你,去年加密货币被黑客攻击的最大原因不是智能合约的 bug 呢?
给你一个提示:
答案:是私钥泄露!
私钥攻击,即滥用密钥材料来窃取资产,是一种新兴的攻击媒介,范围狭窄的智能合约审计和竞赛可能会忽略它。协议对这些攻击的易感程度取决于其设计,特别是其访问控制的成熟度。在这篇博文中,我们将演示如何设计能够安全地容忍私钥泄露的协议,使用多重签名(multisigs)、时间锁(timelocks)、最小权限原则以及从一开始就尽量减少私钥使用的设计方法。
根据 Chainalysis 2024 年的报告,通过黑客攻击窃取的所有资金中,高达 43.8% 源于密钥泄露,比其他任何经过验证的攻击类型高出五倍。私钥泄露是一个明显的例子,说明了一种危险的新兴威胁,每个工程师在设计新的智能合约和协议时都必须考虑。
设计决定风险,但从历史上看,很少有区块链协议认真对待经过身份验证的智能合约访问作为一个重要的风险向量。区块链安全生态系统的运作方式也强化了这种疏忽:由区块链原生公司进行的审计很少将架构访问控制问题标记为正式发现,竞赛平台也积极阻止此类提交,而倾向于代码级别的漏洞。
这种狭隘的关注与其他行业的既定安全实践形成对比,在其他行业,像权限提升和访问控制设计这样的架构风险是安全参与过程中早期解决的基本问题。
在 Trail of Bits,我们的参与会使用我们的 代码库成熟度评估 标记架构访问控制问题。但是,大多数区块链协议只在软件开发生命周期的最后阶段才寻求外部输入和审查,那时几乎没有时间和机会来解决系统性的访问控制问题。
这就是为什么我们需要尽早地转变对话的原因。这篇博客的目的是弥合这一差距,使开发人员能够理解设计能够更好地抵御从第一天开始的私钥泄露的系统所需的知识。
我们将使用一个理论上的过度抵押的借贷提供商作为示例,以说明不同级别的访问成熟度。对于那些不太熟悉借贷协议的人来说,以下功能通常需要某种程度的特权访问控制:
但是,这些访问控制机制的具体设计将极大地改变整个系统对私钥攻击的脆弱性。
这是最不成熟、最基本的访问控制形式。在这种设置中,单个 EOA 对借贷协议的所有管理功能拥有至高无上的权力。根据需要使用此密钥的频率,或者在紧急情况下必须快速使用它的速度,它可能必须存在于连接到互联网的计算机上的软件钱包中。至少可以说,这并不理想。
成熟度级别 1:一个单点故障,一个 EOA 泄露意味着协议完全泄露
像这样的系统的泄露风险是巨大的,而泄露的影响是灾难性的和即时的。一旦私钥被泄露,攻击者可以升级合约、窃取抵押品并摧毁协议。没有人能得到兰博基尼。
缓解此单点故障的最直接步骤是过渡到使用多重签名钱包,任何操作都需要多个密钥持有者的共识。
请注意,虽然此操作降低了泄露的风险,但如果你的私钥被泄露,它不会改变潜在的损害范围。
认识到单个 EOA 控制器的极端危险性,成熟度的下一步是将管理权转移到多重签名钱包,通常是 M-of-N Safe Wallet 或类似的构造。
成熟度级别 2:中心化多重签名模型。需要多个签名者,但仍然存在一个控制点
与 Level 1 相比,此设置绝对是一个改进,因为破坏单个签名者的密钥已不足以让攻击者接管协议。但是,如果足够多的签名者被泄露、串通或被操纵签署恶意交易,仍然存在重大风险和潜在影响:
执行速度:一旦获得第 M 个签名,恶意操作可以立即执行,没有时间进行安全响应。
单点控制:虽然故障点现在分布在 M 个密钥上,但控制点仍然是单一的。多重签名作为一个实体仍然对协议拥有最终权力,即使是例行的、低风险的交易也需要与协议升级相同的签名权限。高度保护的单点控制被利用的一些黑客攻击示例包括 Bybit 黑客攻击、WazirX 和 Radiant Capital。在这些黑客攻击中,攻击者能够破坏单个关键控制点(多重签名),尽管将风险分散在多个故障点之间。
如果你对 Level 2 没有留下深刻印象,我不会责怪你。从 Level 2 转移到 Level 3 是真正的成熟度之旅开始的地方。要达到下一个成熟度级别,需要实施两组控制:时间锁和最小特权原则 (PoLP)。
时间锁是可以创建操作批准和执行之间的“延迟”的合约,从而有时间进行审查和事件响应。
最小特权原则涉及在逻辑上分离角色和职责,仅授予每个角色其特定功能所需的最小权限。这确保了如果一个控制点被破坏,潜在的损害将被控制,并且不会授予攻击者访问无关的、关键的系统功能的权限。
此级别通过解决 Level 2 的核心弱点(执行的即时性,使用时间锁解决;以及控制的集中性,使用 PoLP 解决)代表了成熟度的一大飞跃。Level 3 协议的一些示例包括 Aave、Compound Finance 和 Lido。
成熟度级别 3:时间锁和角色分离为智能合约创建了深度防御
当批准的操作可以在链上立即执行时,社区,更重要的是,你的安全团队,没有时间做出响应。使用时间锁合约允许你创建一个新的、重叠的控制:取消批准的交易的能力。
当批准的交易在时间锁中等待时,团队可以使用 Tenderly 等链下工具来监视它,并根据预期的批准对其进行审查。如果签名了意外的请求,时间锁会使你的事件响应团队有时间审查它、取消它并启动事件响应过程。
对时间锁进行适当的监视和警报至关重要;没有它,该控件毫无价值,如 Beanstalk 黑客攻击 中所见,其中对一天的 time lock 没有进行监视,并导致了一次可以预防的黑客攻击。
通过遵循最小特权原则,我们可以确定系统中至少需要四个角色,这些角色将不同级别的风险责任划分为不同的类别:
核心系统角色:此角色是系统中特权最高的,因此,具有较大的多重签名阈值和时间锁延迟。由于此角色仅限于一项责任(升级合约),因此不太可能经常使用,从而降低了多重签名钱包用于其他活动的操作风险。
运营角色:此角色旨在用于日常协议运营和配置。它使用中等长度的时间锁和中等多重签名阈值,以反映潜在泄露的较低影响。
暂停 guardian 角色:此角色负责在紧急情况下暂停协议。它不应在任何类型的时间锁后面,并且其多重签名阈值应相对较低,以便在紧急情况下可以快速响应。
取消 guardian 角色:此角色可以取消在时间锁中等待的已批准交易。你的安全团队应使用此角色来取消未经授权的批准。它可以是低阈值多重签名钱包或 EOA,具体取决于你的事件响应过程的设计方式。
与 Level 2 相比,Level 3 架构的风险大大降低。我们已成功地从一个控制点迁移到四个,并使用 PoLP 降低了受破坏的控制点造成的影响。现在,你的事件响应团队实际上可以在多重签名泄露事件中阻止事件发生。
但是,风险仍然存在:
复杂性风险:引入多个角色、多个多重签名钱包和多个时间锁会增加系统的复杂性,如果在没有仔细实施和彻底测试的情况下,会为 bug 或错误配置创建新的途径。
过度依赖暂停:暂停 guardian 角色虽然对于紧急情况是必要的,但并不是万能的。攻击者变得越来越高级,并且攻击通常在私有 mempool 中进行,以防止主动识别。随着攻击者变得越来越高级,暂停作为降低攻击影响的机制的效力可能会随着时间的推移而下降。
虽然大多数协议通常对 Level 3 感到满意,但复杂性风险和紧急暂停的有效性降低需要更高水平的访问权限成熟度。Level 4 代表任何成熟协议的最终目标,其成熟度的特征在于消除了对强大操作的需求,并且该协议变得真正去中心化。
Level 4 代表了访问控制设计中成熟度的顶峰:完全消除了对管理操作的需求。这是协议可以做出的对去中心化和信任最小化的最极端的承诺,并且它具有从根本上消除了协议的威胁模型中的访问控制的优势。
成熟度级别 4:系统是不可变的,并且几乎没有控制点
实现 Level 4 需要与迄今为止任何其他级别截然不同的设计方法,并且大多数以 Level 4 为目标的协议都不是“纯”Level 4 协议。Uniswap 和 Liquity 是努力实现 Level 4 的协议的一些最佳示例:它们不需要任何管理管理来促进运营,但确实有一些非常有限的管理控制来允许费用/激励分配。
不要将 Level 4 的理念与简单地将控制权委托给 DAO 或其他官僚机构混淆;Level 4 协议不需要任何类型的管理控制即可成功运行。
对于许多用例来说,Level 3 和 Level 4 之间的设计转变几乎是难以逾越的。考虑一个中心化交易所冷钱包:除非整个交易所变成一个去中心化协议,否则必须对钱包进行某种级别的管理访问才能将资金转移给用户。
对于完全在链上的协议,Level 4 是可能的,但仍然令人生畏;对于我们的过度抵押的借贷系统,我们需要从根本上重构系统的设计。对于以前需要行政管理的每个组件,我们必须设计一个不需要任何管理的替代方案:
由于升级无法修复安全 bug,因此系统的合约必须简单、简洁、经过极其良好的测试、验证和审查。
列出/取消列出资产。在大多数过度抵押的借贷协议中,列出和取消列出资产是行政行为,因为如果添加抵押品是无需许可的,则可能会利用恶意 token 来窃取抵押品。为了使借贷协议达到 Level 4,它可以支持独立的市场部署。在此系统中,要添加对新资产的支持,必须部署一个全新的、独立的借贷协议版本,并专门为该新资产或一组资产配置。然后,用户必须选择与此单独的部署或其他具有不同资产的部署进行交互。
风险参数 代表另一种通常由管理员管理的配置。在 Level 4 借贷协议中,这些参数要么在部署新资产时永久设置,要么永久设置为遵循某种算法参数。由于这些值将被永久设置,因此通过严格的建模、测试和验证来充分表征其行为至关重要。
设计 Level 4 协议具有重大的权衡:不可能进行紧急干预;系统一旦部署就变得不灵活;并且在验证设计的安全性正确性和经济合理性方面存在巨大的初始负担。
尽管存在这些权衡,但这种设计范例从根本上消除了访问控制风险,并且 Level 4 协议中使用的许多设计模式可以改善系统安全性的其他方面。
Level 4 体现了去中心化赛博朋克精神的纯粹愿景,将不变性和用户主权置于行政灵活性之上。
当我们经历了访问控制成熟度的各个级别时,从单个 EOA 控制器的堕落的简单性到 Level 4 的激进的赛博朋克不变性,一个单一的真理变得清晰:你设计协议的方式从根本上决定了其对私钥泄露的脆弱性。
2024 年,43.8% 的被盗资金是由于私钥泄露造成的,因此忽略架构访问控制不再是可以接受的。虽然传统的 bug 搜寻仍然至关重要,但必须在开发过程中更早地做出这些设计决策才能发挥作用。
以下是你可以立即采取的一些主动步骤:
根据成熟度框架评估你的协议。对自己所处的位置要诚实。大多数项目都从 Level 1 或 2 开始。
为你的最高风险管理职能实施时间锁合约。即使是这一项更改也可以显着改善你的安全态势。确保充分监视这些时间锁合约,以确保你可以在未经批准的交易排队时做出响应。
映射协议的特权功能,并按照最小特权原则将其划分为逻辑角色。
考虑你的系统的哪些组件可以从 Level 4 不变性模式中受益,即使你的整体设计需要管理控制。
在 Trail of Bits,我们提倡这种全面的安全观。这就是为什么我们提供设计审查和设计阶段咨询等服务,专门为开发生命周期早期的项目量身定制。这些服务使团队能够获得专家指导和建议,以主动解决这些基本问题,从而补充了专注于后期实施漏洞的传统代码审计。
最终,构建安全的去中心化系统需要的不仅仅是寻找 bug。它需要从第一天起就致力于为运营弹性而设计。通过理解成熟度模型并有意识地选择最小化信任并限制泄露潜在影响的设计模式,你可以构建不仅具有创新性而且真正能够抵御去中心化世界不断演变的威胁的协议。
- 原文链接: blog.trailofbits.com/202...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!