By Cara (Xアカウント @Cara6289)とXiG (Xアカウント @SHXiGi)
2024年5月15日、Sonne FinanceはOptimismチェーンに攻撃を受け、最大2000万ドルの損失を被りました。
攻撃後、Xの@tonyke_botユーザーは、Sonne Financeのトークン担保プール(マーケットとも呼ばれ、CompoundのcTokenに似ている)に残っている約650万ドルを約100ドルで保護したとツイートした。
(https://twitter.com/tonyke_bot/status/1790547461611860182)
攻撃を発見した後、ゾンネファイナンスのプロジェクト側はすぐにすべてのオプティミズム市場を一時停止し、ベース上の市場は安全だと発表しました。
ゾンネファイナンスのプロジェクトサイドは、攻撃を発見した後、オプティミズム(楽観主義)市場をすべて一時停止し、ベース(基地)市場は安全だと発表した。
(https://twitter.com/SonneFinance/status/1790535383005966554)
Attack in the nutshell
Sonne FinanceはOptimismのフォークアップです。ゾンネ・ファイナンス・プロトコルは、個人、機関、プロトコルが金融サービスにアクセスするために、コンパウンドV2をフォークしたOptimism上の分散型融資プロトコルです。ゾンネ・ファイナンス・プロトコルは、ユーザートークン資産を集約して融資流動性のプールを形成し、ユーザに銀行のような融資ビジネスを提供します。Compoundと同様に、プロトコルの参加者は保有するトークンをSonne Financeの融資流動性プールに誓約し、soToken(cTokenのようなもの)を受け取ることができます。soTokenは、ブロックが進むにつれて一定の収益を生み出す利子付きの資産トークンで、SONNEトークンによるインセンティブも付与される。例えば、参加者は一定額のUSDCを差し入れてsoUSDCトークンを取得し、WETHを貸し出してさらなる流通に使用することができます。ソネファイナンスプロトコルでの貸し借りは、多対多の資産関係となり、参加者のアドレスの健全性は自動的に計算されます。プロトコルは参加者のアドレスのヘルスファクターを自動的に計算し、ヘルスファクターが1を下回ると、そのアドレスの担保は清算のためにサポートされ、清算人は一定額の清算報酬を受け取ります。
ユーザーによって預けられた原トークンの数と、鋳造されたsoTokenの数の関係は、主にexchangeRateと呼ばれる変数に関連しています:
上記の式において、totalCashはsoTokenが保有する原資産トークンの数、totalBorrowsは特定の市場で貸し出された原資産トークンの数、totalReservesは総準備金の数(借り手によって支払われた利子を含む)です。totalSupplyは鋳造されたsoTokenの数です。
兌換の際、ユーザーは兌換したい基礎トークンの数redeemAmountを指定し、破棄する必要があるsoTokensの数redeemTokensを計算することができます。exchangeRat"、ここで精度が落ちるわけではないことに注意してください。
この攻撃の本質は、マーケット(soToken)が作成されたときに、攻撃者が最初の担保キャスト操作を行い、少量の基礎トークンで少量のsoTokenをキャストし、その結果、soTokenの「totalSupply」値が小さすぎるということです。攻撃者は、Solidity コントラクトの精度の低下を悪用し、担保化+キャストによって原トークンを預ける代わりに、原トークンを直接 soToken コントラクトに送信する(soToken をキャストしないため、totalSupply は変化せず、totalCash が大きくなる)。これにより、契約の「totalCash」変数は大きくなるが、「totalSupply」は変わらないため、結果的に為替レートは大きくなる。最終的に、攻撃者が原トークンを換金する際、破棄する必要があるsoTokenは、担保化プロセスでキャストされたsoTokenよりも少なくなり、攻撃者は獲得したsoTokenを使用して、原トークンWETH、USDCを他のsoToken(例:soWETH、soUSDC)から借り入れ、最終的に最大2,000万ドルの利益を得る。2000万米ドル。
攻撃に関与したキーアドレス
攻撃準備トランザクション:
https://optimistic.etherscan.io/tx/0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96
Attacking the Profit Taking Transaction:
https://。optimistic.etherscan.io/tx/0x9312ae377ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0
EOA関連を攻略する:
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43
攻撃者(契約)に関連するアドレス:
0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8
0x02fa2625825917e9b1f8346a465de1bbc150c5b9
基礎となるトークン(VELOトークンV2):
0x9560e827af36c94d2ac33a39bce1fe78631088db
脆弱な契約(soVELO、CompoundのcTokenに似ている):
0xe3b81318b1b6776f0877c3770afddff97b9f5fe5
//blockquote>@tonyke_bot user rescue deal:
https://optimistic.etherscan.io/tx/。0x816f9e289d8b9dee9a94086c200c0470c6456603c967f82ab559a5931fd181c2
Attack Flow Analysis
前回
Sonne Financeプロジェクト側は最近、VELO市場をSonne Financeに追加する提案を採択しました(https://twitter.com/SonneFinance/status/1786871066075206044) を採択し、2日後にマルチシグネチャーのウォレットを通じて5つの取引が執行されるよう手配しました (https://optimistic.etherscan.io/tx/0x18ebeb958b50579ce76528ed812025949dfcff8c2673eb0c8bc78b12ba6377b7)を経由して2日後に5つの取引が執行されるように手配し、これを使用してVELOマーケット(soVELO契約)を作成し、金利モデルの設定など、そのマーケットの主要な設定を行いました。
攻撃準備
攻撃準備フェーズでは、以下のことに焦点を当てます。攻撃者は、提案の2日間のロックアップ期間終了後、ゾンネファイナンスの提案情報に基づいてVELOマーケット(soVELO契約)を作成し、キーコンフィギュレーションを設定し、soVELO契約にVELOトークンを差し入れてsoVELOトークンを鋳造すると同時に、攻撃者が保有するVELOトークンを直接soVELO契約に送る。soVELOコントラクトにVELOトークンを預けると同時に、攻撃者が保有するVELOトークンをsoVELOコントラクトに直接送信し、その後の攻撃に備えて交換レートを上昇させる。
具体的な手順は次のとおりです。
2 日間のロックアウトが終わると、攻撃者はまず、プロポーザルで予定されている最初の 4 つの取引の操作を 1 つの取引 (取引 0x45c0cc) にパッケージ化し、これを使用して VELO マーケット (soVELO 契約) を作成し、キー設定を行います。
攻撃者はsoVELOコントラクトの「mint」関数を呼び出してVELOトークンを入金し、soVELOトークンを鋳造する。関数 "exchangeRateStoredInternal "から、この時点ではsoVELOトークンの"_totalSuppl "は0であるため、exchangeRateはステップ1で設定された値であることがわかる。mintTokens = actualMintAmount / exchangeRate "の式により、この時点で鋳造されるべきsoVELOトークンの数は2と計算される。 つまり、このステップで攻撃者はsoVELOコントラクトに "400,000,001 "のVELOトークンを入金し、攻撃者は2個のsoVELOトークンを獲得する。soVELOトークン。
soVELO.mint:
攻撃者は、「2,552,964,259,704,265,837,526」という値の直接VELOコントラクトの形で、soVELOコントラクトにVELOトークンを送りました。soVELO契約はより多くのVELOトークンを保有するが、新規のsoVELOトークンは鋳造されないため、totalSupplyは変化せず、exchangeRateの計算式に従って計算されるexchangeRateはより大きくなる。
攻撃者は保有するsoVELOトークンを数回送金し、最終的には別の攻撃EOA 0xae4aに送金します。
攻撃収益性
攻撃収益性フェーズは、攻撃者がプロポーザルの5番目のトランザクションを実行し、攻撃者にVELOを貸し出すことによって支配されます。攻撃者はVELOトークンをsoVELOコントラクトに貸し出し、ExchangeRateをさらに上昇させ、その後攻撃者は手持ちの価値2のsoVELOトークンを使ってWETH、USDC、その他の原資産トークンを他のsoTokens(soWETH、soUSDCなど)コントラクトに貸し出し、これらの部分が攻撃者の原資産トークンとなる。これらの部分は攻撃者にとって利益となる。交換レートが大きくなり、交換のために破棄されるsoVELOトークンの計算精度が低下したため、攻撃者 はsoVELOトークンのほとんど全てを交換することになる。攻撃者は価値1の余分なsoVELOトークンを使って、他のsoTokenから借りてWETHやUSDCなどの基礎となるトークンを獲得したと理解できる。攻撃者は同じ手法で何度も攻撃を繰り返し、最終的に巨額の利益を得た。
手順は以下の通りです:
攻撃者はタイトルケースの5番目のトランザクションを実行し、提案で指定された貸出係数を設定します。
攻撃者はVolatileV2 AMM - USDC/VELOプールから「35,469,150,965,253,049,864,450,449」という値のVELOトークンをフラッシュレンディングし、攻撃者のフック関数をトリガーします。フック関数では、攻撃者は攻撃を実行し続けます。
攻撃者は自分のVELOトークンをsoVELOコントラクトに送り込み、ExchangeRateをさらに増やします。soVELOは現在、コントラクトに「35,471,703,929,512,754,530,287,976」(攻撃者が3回送金したVELOトークンの合計値)のVELOトークンを保有しています。VELOトークン(攻撃者がVELOトークンを3回送金した合計)。
攻撃者は新しいコントラクトを作成し、0xa16388a6210545b27f669d5189648c1722300b8、コンストラクタで、新しく作成されたコントラクト0xa163(以下、攻撃者)に保有するVELOトークン2枚を転送します。0xa163)に転送する。
攻撃者0xa163は、保持しているsoVELOトークンを使って、soWETHから "265,842,857,910,985,546,929 "の値を持つWETHを借りる。redeemUnderlying "関数を呼び出し、償還されるVELOトークンの価値を "35,471,603,929,512,754,530,287,976"(これは攻撃者が以前にsoVELOコントラクトに譲渡または質入れしたVELOトークンの量である)と指定する。redeemTokens = redeemAmountIn / exchangeRate "という計算式に従って、soVELOトークンの数を計算します。
"exchangeRateStoredInternal "関数から、_totalSupplyが0ではなく2であるため、"exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply "という式を使ってexchangeRateの値を計算する必要があることがわかる。totalReserves)÷totalSupply "とすると、現在の為替レートは "177億3585万1964円756億3773万2614万3988円 "となり、当初の為替レート "200兆円 "よりもはるかに大きい。exchangeRate "200,000,000,000,000,000,000,000,000,00".
新しいexchangeRateに基づいて計算された "redeemTokens "の値は "1.99 "であり、Solidityの下方四捨五入の性質により、"redeemTokens "の値は結局 "1 "となり、攻撃者である0xa163は、以前入金したsoVELOトークンのほぼすべてを、値1のsoVELOトークンを使って換金したことになる。このことは、攻撃者 0xa163 が 1 で預けた VELO トークンのほとんどすべてを換金したことを意味する。同時に、攻撃者0xa163はsoWETHから貸し出されたWETHも「265,842,857,910,985,546,929」という値で獲得しています。
soVELO.redeemUnderlying:
™nbsp;
soVELO.exchangeRateStoredInternal:
攻撃者の0xa163は、借りたWETHと換金したVELOトークンをすべて攻撃者の上位層に転送し、その後自爆しました。
攻撃者はsoWETHの "liquidateBorrow "関数を呼び出し、新たに作成されたコントラクト0xa163が借りた資産の一部を清算し、ロックされた値1のsoVELOトークンを取り戻します。現在、攻撃者は1つのsoVELOトークンしか保有していない。
攻撃者はsoVELOの "mint "関数を呼び出し、2つのsoVELOトークンを得ることを目標に、再びsoVELOトークンを鋳造する。ステップ9でundeylyingトークンを払い戻し、利益を得て市場を去ります。
100ドルで650万ドルを活用する方法
攻撃後、X上の@tonyke_botユーザーは、トランザクション0x0a284cdでsoVELOコントラクトに1,144 VELOトークンを誓約することで、soVELOコントラクトに0.00000011 VELOトークンを鋳造しました。このトランザクションによって totalSupply のサイズと、soVELO に保有される VELO トークンの数 totalCash が変化し、totalSupply の増加が totalCash の増加よりも exchangeRate の計算に大きな影響を与えるため、これ以上の攻撃を防ぐことができる。totalSupplyの増加は、totalCashの増加よりもexchangeRateの計算に大きな影響を与えるため、exchangeRateは小さくなり、攻撃者は攻撃を実行する際にsoVELOを獲得する精度の損失を利用することができなくなり、攻撃を実行することが不可能になります。
資金の追跡
攻撃者たちは、違法な収益を捕らえた直後に資金を送金しました。そのほとんどは、別の住所で攻撃を続けるためか、資金洗浄のために、以下の4つの住所に送られました。paddingleft-2">
0x4ab93fc50b82d4dc457db85888dfdae28d29b98d
攻撃者は198WETHをこのアドレスに送金しました。
攻撃が終わった後、このアドレスは上記の不正な利益を 0x5d0d999e8886581ff8fcb01f35804317f5ed80bbb>に送金しました。
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
攻撃者は次のように送金した。724277 USDC、2353 VELOをこのアドレスに送金し、USDCをイーサに変換しました。 直後、資金の一部がスターゲイトのクロスチェーンブリッジに送金され、不正資金のほとんどがこのアドレスに残されました:
0x4fac0651bcc837bf889f6a7d79c1908419fe1770
攻撃者はこのアドレスに563 WETHを転送しました。563 WETHをこのアドレスに、そして0x1915F77A116dcE7E9b8F4C4E43CDF81e2aCf9C68に転送しました。
今回の攻撃者のマネーロンダリングの手口は比較的専門的であり、その手法も多様化の傾向を示しています。そのため、私たちWeb3参加者にとっては、セキュリティ面でのマネーロンダリング防止能力を継続的に向上させ、KYT、AML、その他の関連ブロックチェーン取引セキュリティ製品を通じて、Defiプロジェクトのセキュリティを向上させなければなりません。
セキュリティに関する提言
精度の損失には注意が必要。精度の損失は、特にDefiプロジェクトにおいて、深刻な金銭的損失につながることが多い、無数のセキュリティ問題につながります。プロジェクトオーナーとセキュリティ監査人は、精度の損失が存在するプロジェクトのコードを注意深くレビューし、脆弱性を回避するためによくテストすることが推奨されます。
攻撃者によって操作され、それによって為替レートが操作されることを避けるため、CompoundのcTokenに似たマーケットの作成と初回の担保キャスト操作は、特権ユーザーによって実行されることが推奨されます。
コントラクトに「this.balance」や「token.balanceOf()」の値に依存するキー変数がある場合、キー変数を変更できる条件を慎重に検討する必要があります。たとえば、ネイティブコインやトークンをコントラクトに転送することで変更できるのか、特定の関数を呼び出すことでのみ変数を変更できるのかなどです。または、特定の関数を呼び出すことによってのみ変数を変更できるかどうか。