攻撃者は、2つの著名なリポジトリに同時展開した偽装パッケージを用いて、開発者を大胆に標的にしました。サイバー犯罪者はRubyGemsに16個、npmレジストリにはさらに37個もの悪意あるライブラリをひそかに紛れ込ませました。彼らは広く使われている依存パッケージを模倣し、微妙なタイプミスを含むパッケージ名を巧妙に選定していました。Windows環境でこれらの偽装パッケージをインストールすると、あらゆる機密情報を無差別に収集するよう設計された悪質な情報窃取マルウェア「StubMaker」が実行される仕組みです。このマルウェアは、ブラウザのパスワード、有効なセッショントークン、クレジットカード情報、暗号資産ウォレットの認証情報、重要なシードフレーズ、そしてTelegram Desktopのアーカイブなどを貪欲に収集していました。両方の攻撃シーケンスを詳細に分析した結果、共通のインフラ、同一のペイロードダウンローダー、そして単一かつ統一されたコア悪性モジュールが使われていることが判明しています。
RubyGemsへの侵入戦略
セキュリティ研究者は、この巧妙なキャンペーンの第一段階を8月15日、RubyGemsのエコシステム内で発見しました。攻撃者はマルウェア配布に際し、古典的なタイポスクワッティング手法を多用していました。この手口では、攻撃者は正規の人気ライブラリと危険なほど似た名前のパッケージを悪意を持って登録します。そして、開発者がインストールコマンドを入力する際、あるいはプロジェクトの依存パッケージを選択する際に単純なタイプミスをすることを計算高く見込んでいるのです。調査担当者は、StubMakerマルウェアに直接結び付く16個のパッケージ名を特定しました。ubnuler、ubnlder、ri18nr、reaker、rakier、orakw、joxn、ise18n、ioe18n、ie18u、iai8n、i1l8n、i18om、activesupmport、brumdler、brundlefです。これらの偽装名は、Bundler、i18n、Rake、Active Supportといった主要ライブラリを意図的に模倣したものでした。
RubyGemsの登録メカニズムを悪用
このキャンペーンの首謀者たちは、RubyGems特有の運用上の癖――一度手放されたパッケージ名の再登録を許可する機能――を悪用しました。少なくともbrumdlerとbrundlefの2つのパッケージは、当初は特定の1つのユーザーアカウントを使って公開されていました。その後、脅威アクターはこれらのパッケージを削除し、名前を配下の別の悪性アカウントへとシームレスに移行させました。ユーザーがある gem の全バージョンを削除すると、システムはそのパッケージ名を即座に再登録可能な状態にします。その結果、他の誰もがそのパッケージ名を正当に取得する権利を持つことになります。つまり、悪性ライブラリを単に削除しただけでは、元のパッケージ名を恒久的に確保・封鎖することにはならないのです。
さらに、別の難読化テクニックも、侵害されたパッケージ間の不穏なつながりを隠す一助となっていました。RubyGemの仕様アーキテクチャにおいて、authorsフィールドは標準的な未検証テキストを受け付けるものであり、パッケージ所有者を認証する識別記録としては機能しません。パッケージの作成者は、実際にパッケージを公開する際に使用したユーザーアカウントとはまったく無関係に、このフィールドへ任意の名前を単に挿入できてしまいます。攻撃者は、同一のユーザーアカウントを通じて複数のパッケージをアップロードしているにもかかわらず、複数の異なるライブラリに異なる作成者名を組織的に設定していました。RubyGemsの公式ドキュメントでは、authorsは、パッケージ名、バージョン番号、説明、連絡先メールアドレスと並ぶ、gem仕様内の標準的なメタデータフィールドであると明確に説明されています。
インストール時の悪性コード実行
悪性コードの実行は、侵害されたRubyパッケージのインストール段階で即座に始まりました。実行のトリガーとして、攻撃者は本来ネイティブ拡張機能を綿密に準備するために設計されたコンポーネントであるextconf.rbファイルを悪用しました。通常、RubyGemsはextconf.rbを実行して、必要な関数やライブラリの有無を厳密に確認し、その後ネイティブ拡張機能のコンパイルに不可欠なMakefileを生成します。RubyGemsの公式ドキュメントでも、この標準的な処理フローが明確に説明されています。
StubMakerは、正規のコンパイルプロセスを完全に偽装した手順にずる賢く置き換えていました。侵害されたextconf.rbスクリプトは、中身が完全に空のall、install、cleanターゲットと、UnixとWindows双方向けの無害なスタブ関数を含む偽装Makefileを生成していました。これらの悪性スクリプトは、意図的に機能的なコンポーネントのコンパイルを一切行わず、単にエラーコードを出さずに実行を終了するだけでした。その結果、RubyGemsはコンパイルが成功したという偽の通知を受け取ることになります。同時に、インストーラーはホストとなるオペレーティングシステムをひそかに識別し、悪性の実行チェーンを密かに起動していました。「StubMaker」という名称は、まさにインストールスクリプトの真の悪意を巧妙に隠したこれらの偽装スタブの生成に由来しています。
Windows向けペイロードの展開
Windows環境で動作する場合、悪性のRubyコードはGitHubから直接、約22メガバイトのファイルのダウンロードを開始しました。攻撃者は事前に、このダウンロードURLをBase64エンコーディングで難読化していました。取得されたファイルはmain.exeという名前で、Rustで書かれた高度なローダーが含まれていました。このローダーの内部には、Go言語を用いて綿密に作り込まれた、約11メガバイトの暗号化された実行モジュールが埋め込まれていました。重要な点として、主要な情報窃取コンポーネント自体を別途ダウンロードする必要はありませんでした。ローダーは自律的に埋め込まれたPEファイルを復号し、必須のMZシグネチャを厳密に検証し、必要なWindows API関数を特定した上で、悪性プログラムをシステムメモリへ直接スムーズに注入していました。
中核となる情報窃取モジュール
内部でwincfgと識別される主要な悪性モジュールは、主にChromiumベースのウェブブラウザを標的として、機密データを積極的に探索していました。標的となったアプリケーションの一覧には、Google Chrome、Microsoft Edge、Brave、Opera、Opera GX、Vivaldi、Yandex Browser、Avast Secure Browser、AVG Secure Browser、CCleaner Browserが含まれています。このマルウェアは、これらのブラウザから保存されたログイン認証情報、貴重なクッキー、有効なセッショントークン、詳細な閲覧履歴、拡張機能の情報、そして極めて機密性の高い決済カード番号を組織的に洗い出していました。
App-Bound Encryptionの回避
厳重に保護されたブラウザデータへのアクセスに成功するため、StubMakerはabe_payload.dllという特定のダイナミックリンクライブラリを容赦なく利用していました。この専用ライブラリは、App-Bound Encryption(ABE)による保護をマルウェアが回避する手助けをしていました。Googleは、悪意あるWindowsプロセスによるローカルシークレットの窃取を大幅に困難にするため、Chromeに積極的にABEメカニズムを実装しています。これらの厳重に保護された暗号鍵は、復号を許可された特定のアプリケーションと本質的に結び付いています。StubMakerは独自のDLLをアクティブなブラウザプロセスへ直接強引に注入し、その信頼された実行コンテキスト内から目的のデータを抽出しようと試みていました。GoogleはApp-Bound Encryptionについて、機密性の高いブラウザデータを盗もうとするマルウェアに対する強固な防御策として展開していることを公式に認めています。
暗号資産とTelegramの標的化
専用の特殊な機能群が、価値ある暗号資産関連データを綿密に収集していました。この悪性コードは、MetaMask、Coinbase Wallet、Phantom、Solflare、Exodus、Electrum、Bitcoin、Litecoin、Dogecoin、Monero、Atomic、Guarda、Trezor Suiteといった、ソフトウェアベースのウォレットや主要なブラウザ拡張機能を積極的に探索していました。さらに、この情報窃取マルウェアはテキストファイルやJSONファイルを徹底的にスキャンし、重要な復元フレーズに似た単語列を執拗に探し出していました。そして、発見した単語を標準的なBIP-39辞書と厳密に照合していました。マルウェアは、成功した発見結果をすべてwallets.txtとseeds.txtという専用ファイルに丹念に記録していました。
注目すべき点として、研究者らは分析したサンプル内に、暗号資産を自動送金する仕組みを一切発見していません。StubMakerはむしろ、後日の不正なウォレットアクセスを可能にするために必要な重要データの窃取に注力していました。Telegram Desktopも、このマルウェアの広範な標的リストに大きく含まれていました。この情報窃取マルウェアは、Telegramクライアントがローカルのセッションデータを安全に保存する特定の場所であるtdataディレクトリを積極的に探索していました。また、プログラムが使用する標準的なインストールパスも入念に確認していました。
同時に、このマルウェアはアクティブなWindowsユーザー名、割り当てられたコンピューター名、具体的なオペレーティングシステムのバージョン、詳細なCPUおよびGPUの仕様、搭載されているRAMの総容量、そして被害者の公開IPアドレスを積極的に収集していました。外部IPアドレスを正確に特定するため、このマルウェアはapi.ipify.orgサービスに問い合わせを行っていました。
データ流出と永続化
StubMakerは収集したファイルすべてを、パスワードで保護された安全なZIPアーカイブへと丹念にまとめ、その後Gofileというファイル共有サービスへ送信していました。アップロードが成功すると、マルウェアはそのアーカイブへの直接リンクを受け取ります。そして、この重要なURLを、暗号化されていないHTTP通信を用いてdresslee.com経由で攻撃者(オペレーター)へ送信していました。このリンクに加えて、マルウェアは侵害されたコンピューターの仕様の詳細な概要と、発見されたパスワード、クッキー、履歴レコード、暗号資産関連データの正確な件数もあわせて送信していました。今回分析されたサンプルは、Windowsサービス、タスクスケジューラ、自動実行レジストリキー、標準のスタートアップフォルダーのいずれを介しても、恒久的な永続化を試みていませんでした。この全体的なキャンペーンは、侵害された依存パッケージのインストール直後に、即座に情報窃取を実行するよう明確に設計されていたのです。
第2波:npmへの攻撃
翌日、調査担当者はStubMakerキャンペーンの第2波、しかも大規模な攻撃を発見しました。8月16日、Axios、Chalk、Commander、Lodash、TypeScript、Reactと紛らわしいほど似た名前を持つ、実に37個もの悪性パッケージがnpmレジストリ上に出現したのです。重要な点として、攻撃者は正規のプロジェクト自体を侵害したわけではなく、代わりに独立した偽の複製パッケージを計算高く公開していました。代表例としては、axois-http、chalk-core、comander-cli、loadashjs、typescirpt-cli、raectjsなどが挙げられます。この悪性な作成者たちは、文字を意図的に入れ替えたり、文字を省略したり、-core、-lib、-cliといった接尾辞を付け加えたりしていました。この戦略は、開発者に対して、悪性パッケージをあたかも著名なプロジェクトに関連する正規の補助ライブラリであるかのように誤認させることを狙ったものでした。
npmのpostinstallスクリプトを悪用
悪性なnpmパッケージ37個はすべてバージョン1.0.0として統一的に指定されており、実質的に同一の悪性なpostinstall.jsスクリプトを含んでいました。npmのエコシステムは、パッケージのインストール直後にpostinstallスクリプトを自動的に実行します。そのため、標的とされた開発者は、そのライブラリを手動でインポートしたり、特定の関数を実行したりする必要すらありませんでした。侵害された依存パッケージをインストールする行為そのものだけで、攻撃を引き起こすのに十分だったのです。
RubyGems版とnpm版とでは、初期実行段階が大きく異なっていました。Ruby版はextconf.rbを悪用し、Base64エンコードされた文字列内にローダーのURLを隠していました。一方、npm版はpostinstall経由で起動し、反復的なハードコードされたキーを組み合わせたXOR演算を用いてURLを難読化していました。URLの復号に成功すると、両方の実行チェーンは同一のWindows向けローダーコンポーネントのダウンロードへとシームレスに移行していました。
Windows Subsystem for Linux(WSL)の標的化
この悪性なnpmパッケージは、Windows Subsystem for Linux(WSL)の存在も巧妙に考慮に入れていました。標準的なLinuxやmacOS環境は、Windows専用に設計されたPEファイルを本質的に実行できません。しかし、このマルウェアはWSL環境を独自の方法で処理していました。Linux環境内で動作するインストールスクリプトが、Windowsのpowershell.exe実行ファイルを直接呼び出していたのです。そして、main.exeをダウンロードし、ホストとなる主要なWindowsシステム上で直接ローダーを起動していました。結果として、WSL環境内で安全に作業していても、Windows専用版のStubMakerに対する保護には一切ならなかったのです。
公開速度と統一されたインフラ
攻撃者が悪性パッケージを公開する速度は、RubyGemsとnpmとの間でかなり異なっていました。Rubyのライブラリは2日間にわたって順次出現しました。ある一群が削除された後、オペレーターはシームレスにユーザーアカウントを切り替え、公開作業を継続していました。それとは対照的に、攻撃者はnpmパッケージの主要な一群を、5つの異なるアカウントを使ってわずか約8分でアップロードしていました。パッケージを複数の一時的なプロフィールに分散させることで、単一のユーザーアカウントへの依存を実質的に減らしていましたが、npmのセキュリティチームは悪性な一群全体を迅速に検知し、根絶しました。
最終的に、統一された単一のコマンド・アンド・コントロール(C2)サーバーが、この2つの異なる攻撃系列を結び付けていました。RubyGems版とnpm版のいずれも、窃取したデータを193.70.34.101:20099/voteへ送信していました。さらに、両方の亜種とも、main.exeをダウンロードするためにまったく同一のGitHub Releaseへアクセスしており、取得されるファイルは同一のSHA-256ハッシュを持っていました。ローダーの内部には、同一のGoベースの情報窃取マルウェアが潜んでいました。つまり、単一のオペレーターが、まったく異なる2つのパッケージエコシステムを通じて、同一の悪性プログラムを同時に拡散させていたのです。
緩和策と修復戦略
研究者らは、StubMaker内に自己増殖のメカニズムを一切確認していません。このマルウェアは正規のライブラリに能動的に感染したり、開発者の正規アカウントを乗っ取ったりすることはありませんでした。また、自らの複製を自律的に公開することもありませんでした。侵害を成功させるには、WindowsまたはWSLシステム上で、特定のおとりパッケージのいずれかを手動でインストールすることが厳密に必要だったのです。
本稿執筆時点で、セキュリティチームはRubyGemsとnpmの両方から発見されたパッケージをすでに根絶していました。さらに、悪性ローダーをホストしていたGitHubアカウントもアクセス不能な状態にされています。セキュリティ専門家は、悪性な依存パッケージがインストールされたコンピューターを直ちに隔離することを強く推奨しています。ユーザーは、すべてのアクティブなブラウザおよびTelegramのセッションを強制的に終了させ、別の信頼できるデバイスを使ってすべてのパスワードを全面的に変更する必要があります。重要なシードフレーズが侵害されたマシン上に保存されていた場合は、関連する暗号資産ウォレットが完全に侵害されたものとみなすほうが、はるかに安全です。ユーザーは、安全で侵害されていない環境で綿密に生成した、まったく新しいアドレスへすべての資金を直ちに移動させるべきです。
翻訳元: https://meterpreter.org/stubmaker-typosquatting-attack/