背景
2023年3月17日、NFTレンディングプラットフォームであるParaspace(現在のParallel Finance)が、価格オラクルの脆弱性を突いた重大な攻撃を受けました。Paraspaceでは、ユーザーはNFTやERC-20トークンを担保として預け入れ、ERC-20トークンを借り入れることで、NFTを売却することなく収益を得ることができます。

ParaSpaceの主要機能の一つに、APE報酬を自動複利運用するApeStakingがあります。APEをステーキングしたユーザーは、APEをcToken化したcAPEトークンを受け取ります。このcAPEは、USDCやWETHなどの資産を借りる際の担保として使用できます。cAPEトークンを預け入れるとpcAPEシェアが付与され、その担保価値はpcAPEの量にrebasingIndex(リベース指数)を掛けることで計算されます。
rebasingIndexは、以下のコードスニペットに示すように、プールされたAPEの合計残高と合計シェアから導出されます。
function _scaledBalanceOf(address user, uint256 rebasingIndex)
internal
view
returns (uint256)
{
return super.scaledBalanceOf(user).rayMul(rebasingIndex);
}
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);
}
}
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;
}
_getTotalPooledApeBalance()関数は、ステーキングされたAPEトークン、未払いの報酬、およびApeCoinStakingコントラクトからのバッファ残高を合計します。
脆弱性分析
この脆弱性はrebasingIndexの操作にあり、cAPEトークンの担保価値を人為的に膨らませることにあります。具体的には、ApeCoinStakingコントラクト内のdepositApeCoin()関数が、あるポジションに対するstakedAmountを増加させます。攻撃者はこれを利用し、自らの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()を介してcAPEを受取人としてAPEトークンを預け入れることで、担保価値を膨らませることが可能となります。
攻撃分析
攻撃者はフラッシュローン攻撃を用い、以下の5つの主要ステップでこの脆弱性を悪用しました。
- 約47,352 wstETHのフラッシュローンを取得し、約46,018 wstETHを供給して複数のコントラクトを通じてcAPEを借り入れました。
- 約12,880,000 cAPEトークンを担保として預け入れました。
- 約1,205 wstETHを約492,124 APEトークンに交換し、1,839,999 cAPEをAPEトークンとして引き出しました。
ApeCoinStaking.depositApeCoin()を呼び出して、2,332,214 APEトークンをcAPEのポジションに預け入れ、プロトコルのstakedAmountを851,662から3,183,876へ(373%の増加)引き上げました。- 膨らんだ担保価値を悪用して、USDCやWETHなどの多額の資産を借り入れ、利益を得ました。
このフラッシュローンを利用したpcAPE価格の操作は、オラクル計算におけるスポット価格の使用を悪用したものです。
まとめ
ParaSpaceのインシデントは、DeFiプロトコルにおけるオラクル操作とフラッシュローン攻撃のリスクを浮き彫りにしました。これは、堅牢で操作耐性のある価格オラクルと、ローンチ前の監査を超えた継続的なセキュリティ監視が不可欠であることを示しています。
BlockSecのPhalcon Securityシステムは、攻撃を自動的にブロックしてユーザー資産を保護することで、能動的な脅威検知と防御の価値を証明しました。この事件は、DeFiプロトコルがスマートコントラクト監査、インフラ監査、リアルタイム監視を含む包括的なセキュリティ対策を実装すべきであることを改めて思い出させるものです。
DeFiセキュリティのインシデントとベストプラクティスに関する詳細については、弊社のセキュリティインシデントライブラリをご覧いただくか、弊社のスマートコントラクト監査およびインフラ監査サービスをご検討ください。
本シリーズの他の記事を読む:
- 序章: 2023年の「すごい」セキュリティインシデント トップ10
- #1: Flashbots Relayの脆弱性を突いてMEVボットを収穫
- #2: Euler Financeインシデント: 2023年最大のハッキング
- #3: KyberSwapインシデント: 丸め誤差の巧みな悪用
- #4: Curveインシデント: コンパイラエラーが引き起こした誤ったバイトコード
- #5: Platypus Finance: 3度の攻撃を生き延びる
- #6: Hundred Financeインシデント: 精度に関連するエクスプロイト
- #8: SushiSwapインシデント: 下手な救出劇が招いた連鎖的な模倣攻撃
- #9: MEVボット 0xd61492: 捕食者から獲物へ
- #10: ThirdWebインシデント: 信頼されたモジュール間の互換性不備が招いた脆弱性
Web3向けのベストなセキュリティ監査
ローンチ前に設計、コード、ビジネスロジックを検証します



