Goモジュール悪用、削除後もプロキシに残る脅威

研究・論文

正規のGoのライブラリ(モジュール)を攻撃者がそっくり複製し、悪性コードを仕込んで配布する——そんなソフトウェアサプライチェーン攻撃を大規模に計測した研究が公開されました。注目すべきは、その悪性モジュールがGitHubから削除(テイクダウン)された後も、少なくとも99.4%がGoの「モジュールプロキシ」経由で取得可能なまま残っていたという指摘です。「消したから安全」という前提が崩れる、という話です。

本記事で取り上げるのはarXivで公開された査読前(プレプリント)の研究であり、結果は今後変わりうる点を最初にお断りしておきます。そのうえで、情シス(情報システム部門のセキュリティ担当者)が押さえておきたい論点を、実務目線で噛み砕きます。

この記事でわかること

  • 研究が計測した攻撃手法(正規モジュールのリパッケージ)の中身
  • なぜ「削除」だけでは悪性パッケージが消えないのか(モジュールプロキシの仕組み)
  • OSS依存を抱える自社にとって何が示唆されるか、現場で何から手をつけるか

何が起きたのか — 正規モジュールを複製して悪性コードを仕込む

研究チーム(Minjae Bae、Carter Yagemann の両氏)は、Goエコシステムにおける自動化された大規模なサプライチェーン攻撃キャンペーンを計測しました。攻撃の流れはシンプルです。

  • 正規のGoモジュールを、攻撃者が管理するアカウント/リポジトリの下にまるごと複製(リパッケージ)する。
  • そこに難読化されたコードを埋め込む。これは「インポートされた時点で発火する(import-triggered)ダウンローダー」で、開発者がそのモジュールを取り込むだけで外部から追加のコードを呼び込みます。

正規のパッケージ名・コードに見せかけることで、開発者の「名前への信頼」を逆手に取る点が厄介です。タイポスクワッティング(よく似た名前で釣る手口)に近い発想ですが、ここでは中身が正規モジュールの複製なので、見ただけでは気づきにくくなります。

どのくらいの規模か

研究は2つの手法を組み合わせています。

  • 手動調査:GitHub上の2,113リポジトリを人手で精査。
  • 大規模解析:「GOAST」と名付けた独自の難読化解除つきAST(抽象構文木)スキャナで、1,230万件のインデックスエントリを走査。

その結果、2,289個の悪性モジュールバージョンを特定したとしています。研究チームの開示を受けて、GitHubは684リポジトリを削除し、GoogleのGoチームは1,377のモジュールバージョンを是正したと報告されています。エコシステム全体での連携対応が必要になる規模だったことがうかがえます。

なぜ削除しても消えないのか — モジュールプロキシのキャッシュ

結論から言うと、Goは「ビルドを壊さない」ためにモジュールをキャッシュして保持し続ける設計だからです。元のGitHubリポジトリが消えても、キャッシュ側に残ったものは取得できてしまいます。

Goでは標準で proxy.golang.org というモジュールプロキシ(ミラー)を経由して依存を取得します。これは、元のリポジトリが消えたり書き換わったりしてもビルドの再現性を保てるようにする、本来はありがたい仕組みです。Go公式も「不正なリリースが元のリポジトリで入手できなくなっても、ミラーには残っていることがある」と説明しており、版を消したい場合は削除依頼ではなくretract(撤回)ディレクティブの利用を案内しています。

つまり、利便性のための設計が、悪性パッケージにとっては「テイクダウン耐性」として働いてしまうわけです。研究が示した「GitHub削除後も99.4%がプロキシ経由で取得可能」という数字は、この構造を裏づけています。

チェックサムがあるのに防げないのはなぜ?

Goには go.sum とチェックサムデータベース(sum.golang.org)があり、取得したモジュールの改ざん検知は効きます。ただし今回の手口は「攻撃者が自分で正規に公開した別パッケージ」です。ハッシュ自体は正しいため、改ざん検知では止まりません。完全性(改ざんされていないこと)と、真正性・安全性(そもそも信頼できる出所か)は別物だ、という典型例です。

情シスにとっての意味 — 「消した=対処完了」という思い込み

自社でGoを使った内製開発をしていなくても、この研究の示唆は他のエコシステム(npm、PyPI、RubyGemsなど)にも通じます。要点は次の3つです。

論点 これまでの前提 研究が突きつける現実
テイクダウン 公開元から削除すれば終息 プロキシ/ミラー/社内キャッシュに残り、取得され続けうる
名前への信頼 正規名なら安全 正規モジュールの複製・なりすましがある
改ざん検知 ハッシュ照合で安全 攻撃者が正規公開した悪性版にはハッシュ照合が無力

「ニュースに名前が出た悪性パッケージを消す」だけのモグラ叩きでは追いつきません。入口(依存を取り込む時点)で止める発想と、どのバージョンがどこで使われているかを可視化する仕組みが要る、ということです。

現場目線の課題

正直なところ、多くの組織は自社製品やアプリが抱えるOSS依存の全体像を把握しきれていません。直接依存だけでなく、依存が呼ぶ依存(推移的依存)まで含めると数百〜数千に膨らみ、「どのライブラリのどの版が、どのシステムに入っているか」を即答できる現場は多くないはずです。

そこへ「削除しても残る」という今回の指摘が加わると、対応の難しさが一段増します。公開元が消えても社内のビルドキャッシュやミラー、CIの依存解決経路には残り続けるかもしれず、「世の中的には対処済み」でも自社内には居座っている、という事態が起こりえます。限られた人員で、外部発表を追いながら社内の依存まで突き合わせるのは、相当に骨が折れる作業です。だからこそ、人手の追跡に頼り切らず、仕組みで可視化・検知する方向に倒すしかない、というのが率直な実感です。

情シスはどうすべきか — まずは公的指針で土台を作る

個別の小手先対策を並べるより、まずは公的機関の手引きで「依存を管理する型」を作るのが近道です。とくにSBOM(ソフトウェア部品表)による可視化は、今回のような「どこに何が入っているか分からない」問題に正面から効きます。

そのうえで現場の実装としては、依存バージョンの固定(ピン留め)導入前のパッケージ審査・スキャンの自動化社内プロキシ/ミラーの棚卸しあたりが入口対策の柱になります。あわせて、開発者へ「正規名でも複製・なりすましがある」という地道な啓発を続けることも欠かせません。便利さ(自動でどこからでも取得できる)と安全性(信頼できる出所だけを使う)はトレードオフになりやすい、という前提を組織で共有しておきたいところです。

まとめ

  • 手口:正規のGoモジュールを複製し、インポートで発火する難読化ダウンローダーを仕込む大規模キャンペーンを、査読前の研究が計測した。
  • 急所:GitHubから削除しても、ビルド再現性のためのモジュールプロキシに99.4%が残存。「消した=安全」は成り立たない。改ざん検知も、攻撃者が正規公開した版には効かない。
  • 打ち手:テイクダウン頼みをやめ、SBOMでの可視化・依存のピン留め・導入前審査など「入口で止める」運用へ。まずはIPAの手引きで土台を作る。

出典・参考

  • Minjae Bae, Carter Yagemann「Beyond Takedown: Measuring Malicious Go Module Persistence in the Wild」arXiv:2606.26291(査読前):https://arxiv.org/abs/2606.26291
  • Go Module Proxy(モジュールプロキシの挙動・retractの案内):https://proxy.golang.org/
  • IPA 情報セキュリティ(サプライチェーン/OSS関連の手引き):上記リンク参照

関連記事もあわせてどうぞ:用語解説(サプライチェーン攻撃の基礎など) / 研究・論文の記事一覧

タイトルとURLをコピーしました