2022年4月30日、攻撃者はNerve Bridge Incidentで発見されたのと全く同じ脆弱性を利用してSaddle Financeを攻撃しました。合計で4,900 Etherが攻撃対象となりました。幸いなことに、そのうち1,360 Etherは我々によって無事救出されました。このインシデントの詳細については、公式ポストモーテムをご覧ください。


全く同じ脆弱性が悪用されましたが、攻撃方法は以前のものとは異なります。新しい攻撃方法は予想されるほど単純ではないため、より詳細な調査を行う価値があると考えられます。本レポートでは、まず脆弱性を簡単に説明し、次にNerve Bridge Incidentにおける元の攻撃方法をレビューします。その後、Saddle Finance Incidentに焦点を当て、攻撃プロセスを解剖することで新しい攻撃方法を解明します。
0x1. デプロイされたコントラクトについて
関連するコントラクトアドレスは以下の通りです。
- 被害者のMetaSwapコントラクト: 0x824dcd7b044d60df2e89b1bb888e66d8bcf41491
- 脆弱なMetaSwapUtilsコントラクト: 0x88Cc4aA0dd6Cf126b00C012dDa9f6F4fd9388b17
検証済みのMetaSwapコントラクトに関連付けられているMetaSwapUtilsコントラクトの表示されているコードは、Settingsで指定されているコントラクトアドレスであるデプロイされたMetaSwapUtilsコントラクトとは等しくないことに注意してください。

そのため、これらの2つのMetaSwapUtilsコントラクトと混同しないでください:)
0x2. 脆弱性分析
脆弱なコントラクトはMetaPoolに属しており、これは以前のブログで詳細に議論されています。 要するに、MetaPoolは元々Curveによって、単一のコインを別の(ベース)プール内のすべてのコインと、その流動性を希釈することなくプールできるように設計されました。これは基本的に、複数の他のステーブルコインで構成されるベースプールのLPトークンとステーブルコインで構成されるプールです。 MetaPoolの設計には懸念があります。つまり、MetaPoolは基本的にステーブルコインの価格を維持するステーブルコインプールですが、ベースプールのLPトークンはステーブルコインではありません。
実際、ベースプールのLPトークンの価格は、ベースプールのgetVirtualPrice関数を呼び出すことで取得でき、その価格はベースプールが請求する手数料の蓄積とともに着実に上昇します。
これを処理するために、MetaPoolは価格計算の前にLPトークンの準備金をスケールアップします。以下に示します。

したがって、ユーザーがLPトークンをステーブルコインと交換する場合、LPトークンの量は価格計算の前にスケールアップされます。 または、ユーザーがステーブルコインをLPトークンと交換する場合、計算されたLPトークンの量は転送と簿記の前にスケールダウンされます。

上記のswapUnderlying関数のコードスニペットは、MetaPool内のステーブルコインとベースプール内のステーブルコインとの間で交換するために使用されます。2つの赤い四角で示されているように、この関数は受け取るLPトークンの量をスケールアップし、交換されるLPトークンの量をスケールダウンします。
しかし、swap関数の実装はswapUnderlying関数と一致していません。具体的には、脆弱性の根本原因は、swap関数(すなわち_calculateSwap関数)で実装された誤った計算にあり、LPトークンの量を適切にスケールダウンおよびスケールアップしません。以下に示すように、左側はMetaPoolの脆弱なコード、右側は修正されたバージョンです。

Nerve Bridge Incidentの攻撃者は、swap関数とswapUnderlying関数の不一致を悪用しました。
(Nerve BridgeはSaddle Financeのフォークプロジェクトであることを忘れないでください。)
その後、Saddle Financeは直ちに脆弱性を修正し、新しいバージョンのMetaSwapUtilsライブラリ(つまりV2)を再デプロイしました。
残念ながら、未知の理由により、Ethereum上のsUSD V2 MetaPoolは、古い脆弱なMetaSwapUtilsライブラリでデプロイされたままになっていました。 その結果、この脆弱性は4月30日に攻撃者によって再び成功裏に悪用されました。興味深いことに、Nerve Bridge Incidentで使用された攻撃方法とは異なり、脆弱なMetaPoolを攻撃するために別の方法が採用されました。
0x3. Nerve Bridge Incidentの元の攻撃方法
元の攻撃方法をレビューするために、以下の図(以前のブログを参照)を再利用します。

脆弱なswap関数が交換されるLPトークン(Nerve 3-LP)の量をスケールダウンしないため、ステップ3での交換量(36,959)は通常よりも大きくなります。
次に、攻撃者は(脆弱性のない)swapUnderlying関数を呼び出して、36,959のNerve 3-LPを(ステップ4と5で)51,494のfUSDTと交換し、1,143のfUSDTの利益を得ます。
この利益は、攻撃者がステップ3でより多くのNerve 3-LPを獲得し、次にswap関数とswapUnderlying関数の不一致を利用して「通常の」価格でそれらを売却することによって説明できます。
0x4. Saddle Finance Incidentの新しい攻撃方法
最近のSaddle Finance Incidentの攻撃者は、swapUnderlying関数を関与させずに、同じ脆弱なswap関数を攻撃するために異なる方法を使用しました。
ここでは、プロセスを具体的に説明するために、1つの攻撃トランザクションを例として取り上げます。

直感的には、ステップ3とステップ4のいずれかの示唆が相殺されるため、利益が存在しないように思えます。
具体的には、ステップ3では、攻撃者はLPトークン(i.e. saddleUSD)が交換される際のスケールダウンがないため、より多くのsaddleUSDをスワップアウトできます。
しかし、ステップ4では、脆弱なswap関数が価格計算の前に受け取るsaddleUSDの量をスケールアップしないため、攻撃者は必然的にLESSのsUSDをスワップアウトすることになります。
しかし、上記の図に示すように、攻撃者はステップ3とステップ4の交換ペアを通じて2,059,771 sUSDの利益を得ました。 利益の理由を理解するために、価格設定メカニズムを深く掘り下げ、攻撃プロセスを理解するために詳細な調査を行う必要があります。
0x4.1 価格設定メカニズム
Saddle FinanceのMetaPoolはCurveの価格設定式を継承しています。

n=2の場合の関数のグラフは、以下の図の青い曲線で示されています。 (式の設計はCurve StableSwap Whitepaperで見つけることができます。)

ここで疑問が生じます。MetaPoolはどのようにしてこの式を使用して各スワップの価格を計算するのでしょうか?
nが2で、ユーザーがdx0のトークン0を使用してdx1のトークン1を交換すると仮定します。
各スワップで、Aは定数として扱われ、
価格曲線に影響を与える唯一の変数であるDのみが変数となります。実際、
Dはプールによって請求される手数料の蓄積とともに増加します。具体的には、
計算プロセスは次の3つのステップに要約できます。
- ステップI:現在のプールの準備金(x0およびx1)を式に入れて現在の
Dを計算します。これは現在の価格曲線を決定します。 - ステップII:x0をdx0だけ増加させ、現在の
Dとx0を式に入れて新しいx1を計算します。 - ステップIII:dx1は、新しいx1と古いx1の差です。
トークン0がベースプールのLPトークンの場合、ステップIIは次のようになります。

ここで、baseVirtualPrice/1e18は攻撃時約1.0033でした。 または、トークンがベースプールのLPトークンの場合、ステップIIIは次のようになります。

Dが価格曲線にどのように影響するかを理解するために、例を使用して説明します。
ユーザーがまずdx0のトークン0をdx1のトークン1と交換し、次にdx1のトークン1をdx0'のトークン0と交換するとします。

上記の図に示すように、ステップ②が最初の交換で手数料を請求するため、Dが増加し、価格曲線が上にシフトします(黒い曲線から青い曲線へ)。
さらに、図はdx0'がdx0'よりも小さい理由を明確に説明しています。
0x4.2 攻撃分析
利益の理由を分析するために、脆弱なMetaSwapUtilsライブラリと修正されたMetaSwapUtilsライブラリをローカルにデプロイし、その時点での被害者プールの状態を使用して攻撃をシミュレートしました。
さらに、このシミュレーション中に、攻撃プロセスを理解するのに役立ついくつかの値を記録しました。つまり、Aは10,000、x_sUSDは8,130,463、x_saddleUSDは9,688,608、その時点でのDは17,818,392でした。

上記の図は、収益性の高い交換ペアのプロセスを説明しています。
- 交換-I:14,800,272 sUSDを9,657,586 saddleUSDと交換
- 交換-II:9,657,586 saddleUSDを16,860,043 sUSDと交換
具体的には、交換-Iは次の2つのステップに分けることができます。
- ①:14,800,272 sUSDを9,625,654 saddleUSDと交換します。現在、
Dは17,931,435に増加しています(請求された手数料のため)。 - ②:脆弱なMetaPoolは交換されたsaddleUSDの量をスケールダウンしないため、プールは31,932 saddleUSDを失います。損失により
Dが15,736,195に減少し、価格曲線がさらに下にシフトします(黒い曲線から灰色の曲線へ)。
同様に、交換-IIも2つのステップに分けることができます。
- ③:価格曲線が下にシフトしているため、同じ9,625,654 saddleUSDで16,891,906 sUSDをスワップアウトできます。これはコストである14,800,272 sUSDをはるかに上回ります。
- ④:脆弱なMetaPoolは、価格計算の前に受け取るsaddleUSDの量をスケールアップしないため、MetaPoolに31,863 sUSDが残ります。これにより、価格曲線が上にシフトします(灰色の曲線から青い曲線へ)。 それにもかかわらず、交換ペアは依然として2,059,771 sUSDの利益を上げています。
明らかに、上記の分析は、攻撃者が新しい攻撃方法を使用して利益をどのように得ることができたかを明確に説明しています。 さらに、交換-IIでMetaPoolに残ったsUSDのため、元の攻撃方法の方が新しい方法よりも効率的であるようです。もちろん、攻撃者はプールを枯渇させるために複数の攻撃を実行する可能性があります。これは実際に観察されています。
0x5. いくつかの教訓
調査によると、2つのインシデントで利益が発生した根本原因は同じです。具体的には、最初の交換(LPトークンを交換するもの)は、脆弱なMetaPoolのDを減らし、それが価格曲線をさらに下にシフトさせます。そのシフトは、その後の価格設定に大きく影響し、その後の利益の主な理由となっています。
BlockSecについて
BlockSecは、2021年に世界的に著名なセキュリティ専門家グループによって設立された、先駆的なブロックチェーンセキュリティ企業です。同社は、Web3の世界のセキュリティと使いやすさを向上させ、その大規模な普及を促進することに専念しています。そのために、BlockSecはスマートコントラクトおよびEVMチェーンのセキュリティ監査サービス、セキュリティ開発と脅威のプロアクティブなブロックのためのPhalconプラットフォーム、資金追跡および調査のためのMetaSleuthプラットフォーム、そしてWeb3ビルダーが仮想通貨の世界を効率的にサーフィンするためのMetaDock拡張機能を提供しています。
現在までに、同社はMetaMask、Uniswap Foundation、Compound、Forta、PancakeSwapなど300社以上の著名なクライアントにサービスを提供し、Matrix Partners、Vitalbridge Capital、Fenbushi Capitalなどの著名な投資家から2回の資金調達ラウンドで数千万米ドルを受け入れています。
公式ウェブサイト:https://blocksec.com/ 公式Twitterアカウント:https://twitter.com/BlockSecTeam



