返回博客

金融数组安全事件分析

Code Auditing
2021年7月19日
阅读约 6 分钟

在7月18日,我们的 DeFiRanger 系统 报告了几笔可疑交易。经过人工分析,我们确认这些交易是针对 Array Finance 的攻击。接下来,我们将以一笔攻击交易为例,说明攻击过程和漏洞的根本原因。

攻击交易

本文使用的攻击交易是: 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa

攻击流程

Figure 1
Figure 1

如图 1 所示,我们发现攻击者在从 AAVE 借入闪电贷后,获得了 186.62 WETH 的利润(本文中不区分 WETH 和 ETH)。

Figure 2
Figure 2

图 2 展示了详细的攻击过程。

  • 首先,攻击者调用了 Array Finance 的 buy 函数。攻击者花费 45.91 WETH,铸造了 430 个 ARRAY 代币,并获得了这些代币。
  • 接着,攻击者调用了一个闭源合约(Array Collater - 0xa800cda5)的 joinPool 函数五次。他/她存入了 676,410.58 DAI + 679,080.46 USDC + 901.82 WETH + 20 WBTC + 20 renBTC,并获得了 726.38 个由 Array Collater 铸造的 aBPT 代币。
  • 攻击者调用 sell 函数,销毁了 430 个 ARRAY 代币,获得了 77.17 个 aBPT 代币。
  • 最后,攻击者调用 Array Collater 的 exitPool 函数。他/她销毁了在前两步中获得的 804.55 个 aBPT 代币,并获得了 748,271.55 DAI + 751,225.08 USDC + 997.62 WETH + 22.63 WBTC + 22.74 renBTC。

从图 2 可以看出,攻击者在第 5 步(图 2:调用 sell 函数)中获利。这是因为获得的 77.17 个 aBPT 代币比第 3 步(图 2:调用 buy 函数)中存入的 49.9142 WETH 更有价值。接下来,我们将分析代码,以了解攻击为何会发生。

代码漏洞

以下代码显示了 Array Finance 的 sell 函数。在该函数中,Array Finance 使用攻击者拥有的 ARRAY 代币余额,并调用内部的 _sell 函数来计算出售 ARRAY 代币可以获得的 aBPT 代币数量。

以下是 _sell 函数的实现。它调用 calculateLPtokensGivenArrayTokens 来获取给定 ARRAY 代币数量可获得的 aBPT 代币数量。然后,该函数销毁 ARRAY 代币并返回 aBPT 代币。

以下显示了 calculateLPtokensGivenArrayTokens 函数的实现。

请注意,有四个参数会影响 amountLPToken 的计算。在读取 saleTargetAmount 后,我们推断其公式如下:

arraySmartPool.totalSupply() * (1 - (1 - amount / ARRAY.totalSupply()) ^ (1000000 / reseveRatio))
 

arraySmartPool 是 Array Collater 的智能合约地址(0xa800cda5f3416a6fb64ef93d84d6298a685d190d)。当攻击者将从闪电贷借来的资金存入 Array Collater 时,arraySmartPool.totalSupply() 的值会增加(如下表所示)。

TxnIndex: 64 arraySmartPool.totalSupply():  110162296218708026400
TxnIndex: 107 arraySmartPool.totalSupply():  165243444328062039600
TxnIndex: 150 arraySmartPool.totalSupply():  247865166492093059400
TxnIndex: 193 arraySmartPool.totalSupply():  371797749738139589100
TxnIndex: 236 arraySmartPool.totalSupply():  557696624607209383650
TxnIndex: 280 arraySmartPool.totalSupply():  836544936910814075475

在阅读 arraySmartPool 的代码后,我们可以确认这一逻辑。以下显示了 arraySmartPool 的 joinPool 函数。

此函数首先调用 SmartPoolManager.joinPool 函数来计算需要从 msg.sender 获取的代币数量(actualAmountsIn)。然后,对于每种代币,它调用 _pullUnderlying 函数将其存入 arraySmartPool。最后,它调用 _mintPoolShare_pushPoolShare 来铸造 aBPT 代币并将铸造的 aBPT 代币转移给 msg.sender

请注意,arraySmartPool 继承自 PCToken。_mintPoolShare 函数调用 _mint 函数,如下所示。

_mint 函数会增加 varTotalSupply 变量,该变量直接由 totalSupply() 返回。因此,每次调用 joinPool 都会增加此值。

利润估算

总结

总而言之,攻击者利用了 Array Finance 的价格机制依赖于 aBPT 代币的 totalSupply,而 totalSupply 是可以操纵的这一漏洞。该漏洞在我们研究论文 DeFiRanger: Detecting Price Manipulation Attacks on DeFi Applications 中已有讨论。

致谢

Junjie Fei, Yufeng Hu, Ziling Lin, Siwei Wu, Lei Wu, Yajin Zhou @BlockSec

(按姓氏字母顺序排列)

关于 BlockSec

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

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

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

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

订阅最新动态
Web3攻击面:渗透测试概览

Web3攻击面:渗透测试概览

加密机构承载所有传统攻击面,并叠加资金处理链。本文提供系统的实用抽象:应用、授权与签名、区块链交互、基础设施四组件模型,说明各自职责、代表实现及继承的攻击面,并将web3特有覆盖细分为五大攻击面:生产与自动化运维、签名意图、审批与提现链、资金逻辑及链上交易与已部署合约。

损失约2300万美元:Cosmos EVM与Moonwell遭利用攻击 | BlockSec Weekly
Security Insights

损失约2300万美元:Cosmos EVM与Moonwell遭利用攻击 | BlockSec Weekly

在报告期(2026/08/22-2026/08/30)内,我们统计5起区块链安全事件,损失约2270万美元;Tectonic被盗约7400万-1.195亿美元,因Cronos回滚至攻击前状态而多数被抹除。重点是六链Cosmos EVM漏洞系列(实现约570万美元),经TAC Chain溯源,共享余额同步漏洞串联下溢与上溢耗尽质押池。报告还分析了Moonwell的抵押品核算与预言机价格操纵组合攻击、Tectonic的预言机价格与凭证代币汇率操纵低流动性抵押品、Ajna清算业务逻辑缺陷,以及Solana上的Rain Card Contract Exploit Series(Ed25519签名验证绕过,涉及Avici、Tria等)。

什么是区块链渗透测试?定义与边界
Security Services

什么是区块链渗透测试?定义与边界

区块链渗透测试尚无公认定义,常与审计、扫描、赏金测试混淆。本文提出工作定义:在约定范围与规则下,对运行系统进行对抗性实测,验证可利用路径与控制链;并指出web3新增的资金处理威胁模型,其关键组合缺口在链下到链上的交接。随后梳理该链条的五项可测能力,并将相关目标分流至代码审计、钱包安全审计、web3安全测试、扫描与赏金测试。

Web3 最佳安全审计方

在上线之前验证设计、代码与业务逻辑,对标业内最高安全标准。

BlockSec 审计
金融数组安全事件分析