シャーロックの脆弱性スポットライトへようこそ、シャーロックの監査中に発見された影響力のある脆弱性に焦点を当てます。 今週は、@0xadrii、@KupiaSecurity、@fによる@plaza_financeコンテストで見つかった誤った担保レベルの計算を調べます。 @farman1094_、そして@0xnovaman33。
脆弱性の概要: getRedeemAmount(...) では、コントラクトは取引後の状態を使用して BOND 償還の担保レベルを計算します。 現在のコード(脆弱) 担保レベル = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * 精度) / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); 償還価格は、この推定担保レベルを使用して最高価格(100ドル)を支払うかどうかを決定するため、攻撃者は(現在の)担保レベルが1.2≤下がるまで混合(場合によっては割引)作成レートでBONDを購入し、推定担保レベルを1.2以上に押し戻す細工されたdepositAmountで計算して、100ドルの上限ですべてのBONDを償還できます。これにより、攻撃者はプールの現在の担保レベルがしきい値に達するまで ETH (「リスクのない」スプレッド) を抽出できます。
攻撃手順: 1) セットアップフェーズ プールのパラメーターの例: - poolReserve = 120 ETH、bondSupply = 3000、levSupply = 200、ETH 価格 = $3075 価格設定ルール: BONDを作成(購入): - 担保レベルが 1.2 ≤の場合: creationRate = tvl * 0.8 / bondSupply - その他: creationRate = $100 BONDの償還(売却): - 推定担保レベル≤ 1.2 の場合: redeemRate = tvl * 0.8 / bondSupply - その他: redeemRate = $100
2) フェーズA – 混合/割引レートでBONDを購入する - (現在の)担保レベル = tvl / (bondSupply * 100) を監視しながら BOND を購入します。 - 最初の購入は、担保レベル>が 1.2 → 1.2 ドルあたり 100 ドル付近で鋳造されているときに発生します。 - その後の購入により、現在の担保レベルが割引された作成レート (たとえば、~94.07 ドル) で鋳造時に 1.2 → 未満に押し上げられ、大きな BOND 残高が安価に蓄積されます。
3) フェーズB – すべてのBONDを最高価格で引き換える - 呼び出し償還(BOND, depositAmount = attackerBondBalance, ...) - コントラクトは、償還後の状態 (bondSupply - depositAmount) と (tvl - depositAmount * 100) を使用して推定担保レベルを計算し、(この例では) 1.2 >値を取得します。 - その推定値がしきい値を超えるため、redeemRate は最大 $100 に設定され、攻撃者は蓄積されたすべての BOND を $100 でキャッシュアウトできます。
4) 利益実現 - 割引買いと 100 ドルの売りの差により、ETH の純利益が得られます。 - PoC 数値: 2 回の購入に 60 ETH を費やすと、償還時に ~61.89 ETH → ~1.89 ETH の利益が得られます。 - 攻撃者は、現在のプール担保レベルが ~1.2 に低下するまで反復し、大まかに抽出できます: 抽出可能な USD ≈ ethPrice × poolReserve − 120 × bondSupply
どのような影響があるのでしょうか? 直接資金抽出/価値漏洩: 攻撃者は割引料金で鋳造し、100 ドルで償還し、プールから ETH を吸い上げます。 Unbounded until threshold: プールの現在の担保レベルが 1.2 ≈に縮小するまで継続できます。 体系的な価格の不一致: 誠実なユーザーがプールの準備金/結果を悪化させることで支払う裁定取引を作成します。
根本的な原因: 価格償還のための取引後状態の使用 このコードは、償還がすでに行われているかのように collateralLevel を計算します。 (tvl - depositAmount*100) と (bondSupply - depositAmount) を使用します。 担保レベル = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * 精度) / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); 1. これにより、攻撃者は推定レベルがしきい値 (> 1.2) を超えるように depositAmount を選択し、現在のプールの状態では正当化できない場合でも、100 ドルの償還率のロックを解除できます。 2. 操作されたメトリックのしきい値ゲーティング 100 ドルの上限の決定は、現在 (取引前の) レベルではなく、この操作可能な推定担保レベルに依存し、価格ゲームを可能にします。
緩和策: 償還後の推定残高ではなく、現在のプール状態から償還価格を計算します。プロジェクトで提案された修正は正しいです。 - 担保レベル = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRECISION) - / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); + 担保レベル = (tvl * 精度) / (債券供給 * BOND_TARGET_PRICE);
追加の硬化(推奨): 1. 価格の単調性: depositAmount が増加しても償還価格が上昇しないようにします (「より多く売れば、より良い単価を得る」ことはありません)。 2. 不変ベースの価格設定: 単一の不変から作成/償還を導き出すため、売買の対称性により一方的な裁定取引が防止されます。 3. スリッページ チェック: 作成と引き換えの両方にユーザー指定の最小/最大レートが必要です。 4. キャップとスロットル: しきい値に近づいた場合のダメージを制限するための、tx ごとおよびブロックごとの引き換え上限。 5. パス間の一貫性: 同じ担保レベルの定義を使用するように、作成パスと引き換えパスを調整します (現在の状態のみ)。
私たちは、この発見を通じて@plaza_financeの確保に貢献できたことを誇りに思っています。 絶対に安全にする必要がある場合は、シャーロックが正しい選択です。
3.27K