#7:ParaSpace事件:業界史上最重要攻撃を阻止せよ!時間との戦い

パラスペース事件:業界史上最悪の攻撃を阻止するための時間との戦い

#7:ParaSpace事件:業界史上最重要攻撃を阻止せよ!時間との戦い

2023年3月17日、価格オラクルの脆弱性により、Paraspaceはハッカーの標的となりました。ハッカーによる3回の試行が失敗した後、BlockSecのPhalconシステムがタイムリーに介入し、救済措置により500万ドル以上のETHを救出しました。救済の詳細や逸話については、こちらのリンクをご覧ください。

ツイートを読むにはこちらをクリック

背景

ParaSpace(現在はParallel Financeとして知られています)は、NFTやERC-20トークンを担保として利用できるNFTレンディングプラットフォームです。これらの資産をParaSpaceに預け入れることで、ユーザーはERC-20トークンを借り入れることができ、NFTを売却することなくNFTから収益を生み出す機会を提供します。

ParaSpaceの興味深い機能の1つは、APE報酬の自動複利計算を可能にするApeStakingです。ParaSpaceプラットフォームでApeStakingに参加したユーザーは、APEのcToken表現であるcAPEを受け取り、それをレンディングプールに提供できます。 具体的には、ParaSpaceではcAPEUSDCWETHなどの資産を借り入れるための担保として使用できます。ユーザーはcAPEトークンを預け入れることでpcAPEシェアを取得できます。担保価値は、pcAPEの量にpcAPEトークンのrebasingIndexを乗算して計算されます。

  function _scaledBalanceOf(address user, uint256 rebasingIndex)
      internal
      view
      returns (uint256)
  {
      return super.scaledBalanceOf(user).rayMul(rebasingIndex);
  }

pcAPEトークンのrebasingIndexlastRebasingIndex関数によって決定され、これはgetPooledApeByShares()関数を呼び出します。後者は、sharesAmount.mul(_getTotalPooledApeBalance()).div(totalShares)という式を使用してインデックスを計算します。_getTotalPooledApeBalance()関数は、プール内のAPEトークンの総価値を表し、totalSharescAPEトークンの総供給量を指します。

  function lastRebasingIndex() internal view override returns (uint256) {
    return ICApe(_underlyingAsset).getPooledApeByShares(WadRayMath.RAY);
  }

  function getPooledApeByShares(uint256 sharesAmount)
      public
      view
      returns (uint256)
  {
      uint256 totalShares = _getTotalShares();
      if (totalShares == 0) {
          return 0;
      } else {
          return
              sharesAmount.mul(_getTotalPooledApeBalance()).div(totalShares);
      }
  }

_getTotalPooledApeBalance()関数は、ApeCoinStakingコントラクトから取得したstakeAmountrewardAmountbufferBalanceの合計を提供するように設計されています。より具体的には、stakeAmountApeCoinStakingコントラクト内のcAPEポジションにステークされたAPEトークンの数を示します。

  function _getTotalPooledApeBalance()
      internal
      view
      override
      returns (uint256)
  {
      (uint256 stakedAmount, ) = apeStaking.addressPosition(address(this));
      uint256 rewardAmount = apeStaking.pendingRewards(
          APE_COIN_POOL_ID,
          address(this),
          0
      );
      return stakedAmount + rewardAmount + bufferBalance;

脆弱性分析

残念ながら、前述のrebasingIndexは操作に対して脆弱であり、cAPEトークンの担保価値を人為的に膨張させることが可能です。

具体的には、ApeCoinStakingコントラクト内では、depositApeCoin()関数は、指定されたポジションのstakedAmountを増加させるように設計されています。depositApeCoin()関数を使用してcAPEポジションにAPEトークンが預け入れられた場合、_getTotalPooledApeBalance()関数からの出力が膨張し、結果としてrebasingIndexが歪むため、エクスプロイトが発生する可能性があります。

  function depositApeCoin(uint256 _amount, address _recipient) public {
      if (_amount < MIN_DEPOSIT) revert DepositMoreThanOneAPE();
      updatePool(APECOIN_POOL_ID);

      Position storage position = addressPosition[_recipient];
      _deposit(APECOIN_POOL_ID, position, _amount);

      apeCoin.transferFrom(msg.sender, address(this), _amount);

      emit Deposit(msg.sender, _amount, _recipient);
  }

  function _deposit(uint256 _poolId, Position storage _position, uint256 _amount) private {
    Pool storage pool = pools[_poolId];
    _position.stakedAmount += _amount;
    pool.stakedAmount += _amount.toUint96();
    _position.rewardsDebt += (_amount * pool.accumulatedRewardsPerShare).toInt256();
  }

攻撃分析

脆弱性が特定されると、攻撃のメカニズムは比較的単純になります。攻撃者はdepositApeCoin関数を介してAPEトークンを預け入れ、cAPEを受取人に設定することで担保価値を膨張させ、その後、より多くのトークンを借り入れました。

BlockSecのブロックされたトランザクションを例に取ると、5つの主要なステップがあります。

  • 約47,352 wstETHのフラッシュローンを取得。複数のコントラクトを作成してcAPEを借り入れるために、約46,018 wstETHを供給。
  • プロトコルに約12,880,000 cAPEを担保として預け入れ。
  • 約1,205 wstETHを約492,124 APEに交換し、1,839,999 cAPEをAPEトークンとして引き出し。
  • ApeCoinStaking.depositApeCoin()を呼び出すことで、2,332,214 APEトークンをcAPEポジションに預け入れ、プロトコルのAPE stakedAmountを851,662から3,183,876に増加させ、約373%増加。
  • インフレした担保を活用して、利益のために多額の様々な資産(USDC、WETHなど)を借り入れ。

まとめ

ParaSpaceのインシデントでは、スポット価格の計算への使用を悪用し、フラッシュローンを使用してpcAPEの価格が攻撃者によって操作されました。このインシデントは、DeFiプロトコルに価格オラクルを組み込む際の注意の重要性を浮き彫りにし、プロトコルの価格オラクルが操作に対して耐性があることを保証する必要性を強調しています。

さらに、Web3におけるセキュリティ侵害の増加傾向を考慮すると、プロトコルは、ローンチ前のコード監査に頼るだけでなく、運用フェーズ全体でアクティブな脅威監視および防止システムを確立することが不可欠です。ParaSpaceのインシデントで実証されたように、仮想通貨ハッキングを自動的にブロックできるBlockSecのPhalconは、攻撃者に先駆けて介入し、ユーザー資産を無事保全することに成功しました。

このシリーズの他の記事を読む

Sign up for the latest updates