
分散型金融 (DeFi) は、ブロックチェーン エコロジーの中で人気のあるプロジェクト形式であるため、そのセキュリティは特に重要です。昨年以来、数十件のセキュリティインシデントが発生しています。
DeFi セキュリティに関する長期的な研究チーム (https://blocksecteam.com) として、BlockSec は独自に多数の DeFi セキュリティ インシデントを発見しており、その研究結果は主要なセキュリティ カンファレンス (USENIX Security、CCS、黒い帽子)。次の期間では、DeFiセキュリティインシデントを体系的に分析し、セキュリティインシデントの背後にある根本原因を分析します。
過去のレビュー:
(1) [BlockSec DeFi 攻撃分析シリーズの 1 つ] 私の独り言: ChainSwap 攻撃イベント分析
(2) 【BlockSec DeFi攻撃分析シリーズ2】すべてを与える:Sushiswap手数料が盗まれる
(3) 【BlockSec DeFi攻撃分析シリーズ3】空を盗み、日を変える:アクロポリス攻撃イベントの徹底分析
0x0.プリアンブル
北京時間の2021年3月9日未明、イーサリアム上の分散型取引プラットフォームDODOの複数のV2クラウドファンディングプールが攻撃され、プール内のトークンがジャコウネコを王子に変えるトリックが仕掛けられた。しかし、その後の分析から、事の展開は明らかに攻撃者の予想軌道から逸脱していたことが判明…。
あなたがイーサリアムの初心者で、ストーリーを読むのが好きなら、以下の 0x1 から読み始めることができます。シンプルで直接的な攻撃分析が好きなら、0x2 まで下にスクロールして読み始めることができます。
最初のレベルのタイトル
0x1. イベントレビュー
「攻撃は成功しましたか?成功しましたが、完全には成功しませんでした。」これは当時のシャオ・アの心理描写かもしれません
No code, no bug
副題
0x1.1 コンセプト分析
DODO V2 クラウドファンディング プールについては何度も言及されていますが、それは何ですか?簡単に言うと資金プールのことですが、この記事でいう資金とは私たちが日々接している法定通貨ではなく、イーサリアム上のトークン(ERC20トークン)のことを指します。この種のファンドプールが初期化されると、チェーン上の 2 種類の貴重な ERC20 トークンがこのプールのトークンペアとして設定され (この点を覚えておいてください。後でテストします)、ユーザーはこれらによって提供されるサービスを利用できるようになります。普通にプールします。 DODO V2 クラウドファンディング プールに対するこの攻撃では、Little A はプールが提供するフラッシュローン サービスを利用しました。
フラッシュローンは通常のローンと比べ、無担保で多額の資金を借り入れ、返済前にステータスをロールバックするという特徴があります。簡単に言うと、手ぶらで大丈夫です 1回の操作で最後に借りたお金がなくなっても、まだ取り戻せなくても問題ありません 関係するステータスはすべて融資前の状態にロールバックされます借り手にとっての唯一の損失は、手続き以外にあり、手数料に加えて時間だけかもしれません。フラッシュ ローンを使用するロジックも非常にシンプルです。つまり、ユーザーが資金プールからお金を借りる --> 借りたお金で運用する --> お金を返済するというもので、これらは 1 回の取引で完了する必要があります。
関連する概念を簡単に理解した後、Little A の動作を見てみましょう。
0x1.2 Xiao Aのコケティッシュな作戦
小さなAは次に2つのことをしました。
最初に 2 つの ERC20 トークン コントラクトを作成します。率直に言うと、2 つの偽造コイン (無価値であるため) は FDO および FUSDT と呼ばれます。これら 2 つの偽造コインを作成した後、A はそれらを DODO プールに預けます。攻撃される。
Little A が 2 番目に行ったことは、DODO V2 クラウドファンディング プールのフラッシュローン サービスを利用することでした。前述したように、フラッシュ ローンを使用するロジックの 1 つは、借りたお金を運用することです。この記事の主人公である Xiao A は、このリンクで悪戯をしました。
Little A は、この DODO V2 クラウドファンディング プールは人為的に再初期化でき、制限がないことを発見しました。その後、Little A はお金を貸した後にプールを再初期化し、初期化時に設定されたトークンのペアは、Little A 自身が作成した 2 つの偽造コイン FDO/FUSDT になりました (これは前述のテスト ポイントであり、現在はテストに合格しています。) 。そして、リトル A は、お金を借りる前に上記で最初に行ったことにより、十分な量の 2 種類の偽造通貨をこのプールに事前に入金しました。これにより、プールはリトル A の借金の状況をチェックすることになり、チェックされたトークンはもう存在しません。以前の本物の通貨ではなく、A が預けた偽の通貨であり、金額は十分です。このようにして、A さんは偽札を使って本物のお金を出しました。
上記のプロセスと簡単に類推できますが、詳細は示しません。銀行があり、この銀行は上記の資金プールにたとえることができます。同時に、銀行には口座を管理するための小さな帳簿もありますが、小さな帳簿のホームページには[銀行は人民元のみを扱い、準備金は100です]という記録があります。他の通貨としては、米ドルまたはベトナムドンのいずれかです。ユーザーもそこに預金することができるが、銀行はユーザーのことなど気にしておらず、口座は小さな帳簿に保管されるものの、チェックの際には人民元に関係する記録のみが参照される。
クラウドファンディングのプールを再初期化できるという問題を類推すると、次のように理解できます。この小さな本には問題があります。問題は、ホームページのルール[銀行は人民元のみを取り扱います]が鉛筆で書かれており、この小さな本が窓に置かれており、部外者が消しゴムと鉛筆で変更できることです。その後、この問題はリトル A によって発見されました。彼は最初にこの銀行に 100 ドンを入金し、銀行は [リトル A が銀行に 100 ドンを入金] と記録します。次に、小さな A は 100 RMB を貸すために銀行に行き、銀行は [小さな A は銀行から 100 RMB を借りました] と記録します。なお、銀行はすべてのユーザーによる人民元の借入と預け入れを確認し、準備金額と比較して、人民元を借りて返済していないユーザーがいないかどうかを確認します。
A君はお金を借り終わるとすぐに、用意していた鉛筆と消しゴムを取り出し、小さな本のホームページの規定を「当銀行はベトナムドンのみ取り扱い、準備金は100ドル」に変更しました。その後、ベトナムドンのみを扱うように規定が変更されたため、銀行が金額を確認したところ、ベトナムドンの準備金額はリトルAが預けたベトナムドンの金額と同じであり、誰も借りていないことが判明しました。銀行のお金。そしてシャオ・アさんは貸した人民元を受け取り、振り返ることなく立ち去った。
DODO V2 クラウドファンディングプールを攻撃するという Little A のアイデアは上記の通りであり、Little A が次にしなければならないことは、アイデアを実際の行動に移すことです。この記事でコントラクトコードレベルから分析する攻撃は上記の攻撃ですが、話はまだ終わっていません。ストーリーを読みたくない人は、0x2 の攻撃分析セクションまで直接スクロールしてください。残りの審査員のためにストーリーを続けさせてください。
0x1.3 攻撃プロセス: 山道十八曲
1回目 カマキリがセミを捕まえ、コウライウグイスが追いかける
本を続けましょう。
プロジェクト当事者、つまり DODO は同じロジックで複数のプールを作成しており、これらのプールには同じ抜け穴があります。 Little A が初めてターゲットとしたプールは (WSZO/USDT) プールで、WSZO と USDT は 2 つの貴重なトークン (ERC20 トークン) です。喜んで攻撃ロジックをトランザクションに書き込んだ後、彼は横になってお金を集めようとしていましたが、この瞬間に問題が発生しました。
イーサリアムでの取引には取引手数料があり、ユーザーからマイナーに支払われることは承知しています。したがって、マイナーは自らの利益を最大化するために、保留中のプールからトランザクションをパッケージ化してチェーンに載せる準備をするときに、各トランザクションのトランザクション手数料を確認し、順番に整理します。まずはチェーン。そして、イーサリアムの分散メカニズムにより、ここでも暗い森の法則が適用されます。攻撃者、裁定者、または DeFi (分散型金融) プロジェクトの初期実行者が世界中に潜んでいます。ターゲットを見つけると群がってきます。最終的に誰が成功できるかは、取引手数料を誰が支払うかによって決まります。テクノロジーやその他の要因に加えて、背が高くなります。
主人公の小さな A の話に戻ります。彼は抜け穴を見つけて、その機会を利用して大金を稼ごうとしましたが、小さな A の行動は別のキャラクター、つまり突進ロボットによって発見されました。この突進ロボットをリトル B と呼びましょう。小さな B は取引手数料について大騒ぎし、取引のガソリン価格を値上げし、それによってこの取引の取引手数料も増加しました。これにより、マイナーはトランザクションをパッケージ化するときに、最初に小さい B のトランザクションをパッケージ化します。一般に、このようなリトル B の操作をフロントランニングと呼びます。小規模な A トランザクションをパッケージ化する番になったとき、WSZO/USDT プール内の WSZO と USDT は空で、価値のないもの (FDO/FUSDT) だけが残りました。
幼い A は、今回の失敗は単なる通常のフロントランニング トランザクションであると考えた可能性があり、古い手口を繰り返しました。ただ、今回はターゲットが(ETHA/USDT)プールに変更されており、Little Aは強盗を防ぐために、今回の取引での取引のガソリン価格を値上げしました。しかし、小さなAは、自分が小さなBに狙われていることを知りません。
同じルーチンと同じ方法で、リトル A は再びリトル B に奪われました。
二度目、鄭耀進は途中で殺された
これまでのところ、リトル A は 2 回の攻撃でリトル B のためにウェディング ドレスを作り、自分自身も取引手数料を失いました。 A ちゃんはとても怒っていたので、痛みから学び、次のプール (wCRES/USDT) を目指しました。そして今度は、小さなAが小さなBの監視を回避することに成功しました。物事はリトル A が成功しそうなところまで発展しましたが、実際には彼はリトル A と冗談を言うのが好きです。
3回目の攻撃はリトルBを回避しましたが、リトルAはお金の引き出しに成功した後、そのお金を自分のアドレスに直接転送せず、お金を受け取るための新しい契約を作成しました。 A さんのアイデアは、まずこの新しい契約にお金を一時的に保管し、それから自分の口座に送金することです。しかし、リトルAの盗んだお金を一時的に保管するというもう一つの抜け穴があり、それは誰でもこの契約から契約上の資金を引き出す(引き出す)ことができるというものです。
However, this contract had a loophole that allowed anyone to withdraw assets from it.
たまたま、この脆弱性は別のキャラクター (Little C) によって発見されました。そこで、リトルAがこの契約で盗まれたお金を取り戻すためのトランザクションを発行したところ、二人ともまた奪われてしまいましたが、今度は先制者はリトルCになりました。
これを見て、Little A はフロントランニング トランザクションの攻撃者であると同時に被害者でもあります。この波では、小さな A は鶏を盗んだものの、お金を失ったとみなすことができます。
3回目 頑固な子A
前述したように、同じ論理的な抜け穴を持つ複数のプールが存在します。リトル A は再び 4 回目の攻撃を開始する準備ができています。今回は、ターゲットが (DODO/USDT) プールに変更されます。今回、小さな A は賢いことを学びました。一方で、彼は盗まれたお金を一時的に保管する契約を新しい契約に置き換えました。また、一方で、小さな A はまた、トークンの転送プロセスを 1 つのトランザクションに結合して、不正行為を回避しました。 3回目 2回目の攻撃でリトルCにさらわれた件。しかし今回、南の壁にぶつからず、振り返らなかったリトルAは、ついに偽造通貨(FDO/FUSDT)で本物のお金(DODO/USDT)を手に入れることに成功しました。
第4章 狂って自分を噛む
ようやく4回の攻撃が成功したので、リトルAは満足しましたか?事実は、答えがノーであることを示しています。
小さなA君はどう思ったかは分かりませんが、紆余曲折を経てようやく成功したのかもしれません、そのせいで興奮しすぎてしまったのかもしれません。この 5 回目の攻撃では、彼のターゲットは (wCRES/USDT) プールでした。見覚えがあるでしょうか?それは正しい!このプールはまさに、リトル A の 3 回目の攻撃のターゲット プールです。 3 回目の攻撃の後、プールは (wCRES/USDT) プールから (FDO/FUSDT) プールに変わりました。つまり、本物のコイン プールが偽のコイン プールになりました。したがって、この一連の攻撃で、リトル A が同じ攻撃ルーチンを使用して得た結果は、新しい偽造コインと古い偽造コインの交換に他なりません...
そして、この2枚の偽コインはシャオ・ア自身が作ったものでした。もしかしたらシャオアは今でも懐かしい人なのかもしれない…。
リトルAの物語も終わりに近づいています。おそらく、イーサリアムは攻撃者にとって暗い森であり、この特別なアリーナでは狩人と獲物のアイデンティティは静的ではありません。あなたが深淵を見つめるとき、深淵もあなたを見つめているということを常に覚えておいてください。
OK、次のステップは深刻な攻撃分析リンクです。
最初のレベルのタイトル
0x2. 攻撃分析
理解を容易にするために、以下では分析する例として 3 番目の攻撃を取り上げます。関係するプールは (wCRES/USDT) プールです。
0x2.1 コード分析
以下で説明する関数はすべてファンド プール (wCRES/USDT) の契約コードに由来しており、この攻撃に関与しています。
0x2.1.1 getVaultReserve 関数
まず getVaultReserve 関数を見てください。この関数の関数は非常に単純で、ユーザーがこの関数を呼び出すと、現在のプール内のトークン ペアの予約が返されます。
0x2.1.2 フラッシュローン機能
上の写真は、この攻撃におけるファンドプール契約のフラッシュローン機能です。ユーザーがこの関数を呼び出すと、ユーザーによって渡されたbaseAmountとquoteAmountの2つのパラメータに従って、対応する数のトークンがパラメータassetToで表されるアドレスに転送されることがわかります。この時点で、フラッシュローンのローンリンクが完了します。コードを見ると、データが空でない限り、外部ロジックがトリガーされます。そして、この外部ロジックは呼び出し元自身によって実装されており、この外部ロジックが実行されるときこそ、この攻撃が実現します。
0x2.1.3 初期化関数
上図は、この攻撃で最も重要な初期化関数 init であり、この関数が外部から呼び出されていることがわかりますが、最も重要なことは、この関数が次の 2 つの特徴を持っていることです。
【許可不要】 これは、誰でも外部からこの関数を呼び出すことができることを意味します。
[繰り返し呼び出すことができる] とは、プールの構築時に 1 回呼び出される場合を除き、いつでも init 関数を呼び出してプールを再初期化できることを意味します。
呼び出し元がこの関数を呼び出すと、渡された 2 つのパラメーターbaseTokenAddress と quoteTokenAddress を使用して、それぞれ変数 _BASE_TOKEN_ と _QUOTE_TOKEN_ が再割り当てされます。そして、これら 2 つの変数の変更は、このプールのトークン ペアも変更されることを意味します。これが、wCRES/USDT プールが FDO/FUSDT になる理由です。
0x2.2攻撃プロセス
攻撃トランザクションの流れを以下の図に示します。
取引フロー分析では、当社チームの取引分析ツールを使用できます。https://tx.blocksecteam.com/
Step 0
攻撃者は最初に 2 つの ERC20 トークン コントラクト (FDO と FUSDT) を作成しました。これは、単純に 2 つの偽造トークン (価値のない) を作成したと理解できます。そして、大量のこれら 2 つのトークンを自身のアドレス (0x368a6) に転送し、後続の攻撃への道を開きました。
Step 1
攻撃者は、ファンド プール コントラクトの getVaultReserve 関数を呼び出して、プール内の wCRES と USDT の現在の準備金を取得し、次の攻撃に備えます。
Step 2
ステップ 1 で取得した準備金に基づいて、攻撃者は 2 つの偽造通貨契約の transferFrom 関数を呼び出し、準備金よりわずかに多い偽造通貨 (FDO および FUSDT) をファンド プール 契約 (DLP) に転送します。フラッシュローン機能の残高チェックは合格できます。
Step 3
次に、攻撃者はファンド プール コントラクト (DLP) のフラッシュローン機能を呼び出し、ファンド プールの準備金よりわずかに少ないリアル コイン (wCRES および USDT) を貸し出します。
Step 4
flashloan 関数は、攻撃者が事前に設定したコントラクト アドレスに wCRES と USDT を転送した後、攻撃者の外部ロジックを自動的に呼び出します。攻撃者は、外部ロジックの実装で wCRES/USDT プールの初期化関数 init を呼び出し、プールのトークン ペアを FDO/FUSDT に置き換えました。
Step 5
以下の図に示すように、flashloan 関数は外部ロジックを実行した後、現在のプールのトークン (トークン) 残高をチェックします。ただし、プールのトークンペアが FDO/FUSDT に置き換えられるため、baseBalance と quoteBalance で表される残高も FDO と FUSDT の残高になることに注意してください。
同時に、攻撃者はStep 2 最初のレベルのタイトル
0x3. 概要とセキュリティに関する推奨事項
この攻撃の主な理由は、DODO V2 クラウドファンディング プールの init 関数です。この関数の呼び出しを見ると、通常のロジックでは、この関数は最初にプールを構築するときに 1 回だけ呼び出すことができ、その後アクセス許可を設定する必要があり、繰り返し呼び出すことはできません。攻撃者は、init 関数を繰り返し呼び出してプールを再初期化できるという脆弱性を利用し、フラッシュローンと組み合わせてプール内の本物のお金を偽のお金で引き出し、攻撃を完了しました。
したがって、プロジェクト関係者に対する私たちの提案は次のとおりです。
権限要件が低いためにコア機能が誤用されてしまうことによる損失を避けるために、プロジェクト契約の主要な機能に関する権限のレビューを適切に行ってください。
最初のレベルのタイトル
0x4.リファレンス
副題
記事に含まれる外部アドレスと契約アドレス
この記事で取り上げる取引
最初の攻撃
二度目の攻撃
3回目の攻撃
4回目の攻撃
5回目の攻撃