背景

2025年2月21日の夕方、Bybit取引所に関連する重大なセキュリティインシデントを検出しました。その夜02:16 UTCに、 Bybit Cold Walletによって開始された大規模な送金が検出されました。

https://etherscan.io/tx/0xb61413c495fdad6114a7aa863a00b2e3c28945979a10885b12b30316ea9f072c、

401,346 ETHが送金され、その価値は約15億米ドルです。複数回の確認の結果、これはBybitに対する攻撃であると判明しました。

Safe{Wallet}について

数々の分析と調査を経て、事件全体の大まかな経緯がより明らかになった。攻撃者はまずフィッシングを使用して Safe{Wallet} とコア開発者を攻撃し、AWS の CloudFront または S3 のアクセスキーを盗みました。次に、アクセス キーを使用して、Safe{Wallet} のフロントエンドに悪意のあるコードを挿入します。偶然にも、影響を受けた当時、Safe{Walllet} は archive.org の Wayback Machine に含まれていました。 Wayback Machineによると、Safe{Wallet}のフロントエンドコードに、2025年2月19日17時28分33秒に悪意のあるコードが挿入されたという。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

悪意のあるコードは、フロントエンド js ファイル _app-52c9031bfa03da47.js に表示されます。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

悪意のあるコードのコアロジックを次のように取り出してみましょう。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

全体のロジックは比較的単純です。 sd.getAddress()、つまりSafeウォレットのアドレスが["0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4","0x19c6876e978d9f128147439ac4cd9ea2582cd141"]の場合、

次に、アドレスを0x96221423681a6d52e184d440a8efcebb105c7242に設定します

データは 0xa9059cbb000000000000000000000000000bdd077f651ebe7f7b3ce16fe5f2b025be29695160 に設定されています...

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

そのうち、悪意のあるjsコード:0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4では、

このウォレットアドレスは、Bybit から盗まれたマルチ署名コールドウォレットアドレスです。つまり、攻撃者の悪意のあるコードは、Bybit のコールドウォレットを標的とした攻撃です。これの利点は発見される可能性を最小限に抑えられることです。他のユーザーに気づかれないようにします。 Safe ウォレットが呼び出そうとしているコントラクト アドレスである宛先アドレスは 0x96221423681a6d52e184d440a8efcebb105c7242 です。このスマート コントラクトはオープン ソースではありません。逆コンパイルすると、コントラクト関数が非常に単純であることがわかります。転送機能のみを実装します。この機能は、コントラクトの slot0 を受信者のアドレスに変更することです。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

se.data.data は上記のコントラクトを呼び出すための calldata です。最初の 4 バイトは 0xa9059cbb で、これは transfer(address recipient, uint256value) の署名です。後続のパラメータは、受信者: 0xbdd077f651ebe7f7b3ce16fe5f2b025be2969516、値: 0 です。Bybit ウォレットが使用する Safe{Wallet} のバージョンは 1.1.1 であり、このバージョンでのウォレットのコントラクト呼び出し実行ロジックは、MultiSig Address-[Signature]->Wallet MasterCopy Proxy-[Delegatecall]->Safe Wallet Logic Contract-[Delegatecall | calldata]->TargetContract Address なので、実際に変更されるのは Wallet MasterCopy Proxy の slot0 であり、ウォレットが正式に乗っ取られたことを意味します。

悪意のあるコードでは、別のアドレス 0x19c6876e978d9f128147439ac4cd9ea2582cd141 が、攻撃者が攻撃プロセスをテストするために使用するテスト アドレスです。つまり、悪意のあるコードは 2 つのウォレットを乗っ取ります。ウォレット 1 は Bybit のコールド ウォレットであり、ウォレット 2 は攻撃者のテスト ウォレットです。 Bybit Cold Wallet のコードバージョンは 1.1.1 であるため、攻撃者は Safe Wallet バージョン 1.1.1 も作成しました。作成されたトランザクションは次のとおりです: https://etherscan.io/tx/0x8df9884dd022f900ea7ebcbd0d47356137e3dcc8032e36d8706bed86f158f7c8。 Safe App は古いバージョンのウォレットを作成できなくなったので、攻撃者はどのようにして古いバージョンのウォレットを作成したのでしょうか?

攻撃者が Proxy Factory 1.1.1 の createProxyWithNonce を呼び出して、Ethereum メインネット上にテスト ウォレットを作成したことがわかります。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

したがって、createProxyWithNonce を使用して、Sepolia テスト チェーン上にバージョン 1.1.1 の Safe ウォレットも作成しました。作成トランザクションは https://sepolia.etherscan.io/tx/0xa7ce1ce4cb5ccb65eb9a35842ebde8f9a161dd561bce80528dbb7362efc33ff0 で、作成されたウォレットアドレスは 0xfdfd440e9d920a8a577eb3d586547986b889ad56 です。

ただし、作成したウォレット アドレスは Safe アプリにインポートできません。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

Safe がマルチシグ ウォレットを作成するためのコードは次のようになります。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

Safe は、create2 を使用してプロキシを作成するウォレットを作成するため:= create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)、同じアドレスのウォレットを作成するには、MasterCopy、initializer、および saltNonce を同じに保つだけで済みます。そのため、攻撃者と同じパラメータを使用して、Ethereum メインネット上の攻撃者と同じアドレス 0x19c6876e978d9f128147439ac4cd9ea2582cd141 を Sepolia テスト チェーン上に作成し、https://sepolia.etherscan.io/tx/0x3ec6ef599d1df75c9f255f4c1a0edaed8ef992a4fd6ea90af50a05ca962c9e69 でトランザクションを作成しましたが、それでもアドレスを Safe アプリにインポートできませんでした。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

攻撃者が Ethereum メインネット上で作成したアドレスは、Safe アプリに正常にインポートできます。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

その後、公式ドキュメントで、Safe Wallet は作成されたウォレットをインデックスするために L1 のトレースベースを使用していることがわかりました。https://github.com/safe-global/safedocs/blob/f487ace5e0221437277bd9d56fb340794dda424c/pages/advanced/cli-guides/recovery-safe-deployment.mdx#L42

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

理論的には、攻撃者が Safe アプリのフロントエンド コードを改ざんし、Safe アプリを使用している場合にのみ攻撃が発生するため、Factory を通じて作成されたすべてのウォレットは Safe アプリを使用できます。ただし、Factory 1.1.1 で作成した Safe ウォレットはインデックス付けできないため、テストできませんでした。また、攻撃者が作成したウォレットが Safe によってどのようにインデックス化されるのかもわかっていません。

安全性について

Bybit は Safe{Wallet} の古いバージョン 1.1.1 を使用しているため、最新バージョン 1.4.0 は、この攻撃で使用される攻撃方法 (slot0 を使用してウォレットを乗っ取る) に対しては効果がありません。

ゼロアワーテクノロジーBybit攻撃事件の徹底調査 パート1 - Safe{Wallet}について

delegatecall が call に変更されていることがわかります。これは、呼び出されたコントラクト自体のスロットのみを変更でき、プロキシのスロットは変更できないことを意味します。しかし、将来的には同様の攻撃を防ぐ必要があります。攻撃者は、資産を転送するためのトランザクションを直接構築する可能性があります。したがって、署名する前に Safe に組み込まれている Tenderly を使用して取引をシミュレートし、正しいことを確認してから署名することをお勧めします。