PR 本記事には広告(Amazonアソシエイト・もしもアフィリエイト・A8.net等)が含まれます。掲載情報の正確性には努めていますが、商品の詳細は必ずリンク先で最新情報をご確認ください。
CTF・セキュリティ学習

【ソフトウェアサプライチェーン編】依存ライブラリと更新経路を守る|CTF思考フレームワーク #34

かも次郎とアンペンが「ソフトウェアサプライチェー」を解説するマスコットイラスト
安全に生きたい編集部

こんにちは、アンペンです!

前回は、テンプレートエンジンに混ざる悪意でRCEに至るSSTIを扱いました。

今回は、自分のコードではなく『使っているライブラリ』が攻撃面になるソフトウェアサプライチェーンを見ていきます。依存パッケージから刺される構図と、その守り方を学びましょう。

サードパーティのライブラリって、誰でも使ってるよね?それで攻撃されるの?

便利な反面、依存ツリーのどこか1つが悪意を持つと、自分のコードも一緒に動かされてしまう。これがサプライチェーン攻撃の怖さだよ。

ここまでは『自分のコードの穴』を中心に見てきました。今回はガラッと視点を変えて、“自分のコードは完璧なのに刺される”という、ちょっと理不尽な話です。現代のアプリは、世界中の人が書いたライブラリの上に成り立っています。その中のたった一つが悪意を持つだけで、あなたのアプリごと乗っ取られてしまう。今日は食材の流通網にたとえて、この“見えない他人任せ”のリスクをほどいていきます。

まず結論

現代のアプリは依存パッケージの上に成り立っています。誰かが悪意あるバージョンを公開・乗っ取り・誤認させると、自分のアプリで実行されてしまうのがサプライチェーン攻撃です。守りはlockfile固定・自動スキャン・SBOM管理・信頼レジストリ運用の組み合わせ。

この記事で分かること

  • サプライチェーン全体がコードの一部になっている理由
  • typosquatting・dependency confusion・悪性アップデートの3型
  • lockfile・SBOM・脆弱性スキャンの守り方
難易度:中級向け 所要時間:11分 体験:依存ツリーを点検 おすすめ:#33の後

📖 はじめてのWebセキュリティ #34|ソフトウェアサプライチェーン編
『便利な依存』が攻撃面になる構造を、現実の運用観点で学びます。 シリーズ一覧を見る →

⚠️ 大事なお約束
この記事の確認は、自分が管理するプロジェクトの依存関係点検にとどめてください。他者のレポジトリに対する依存改ざん・パッケージ乗っ取り試行は犯罪に該当します。

依存は『ピラミッド構造』

現代のアプリは、自分が書いたコードよりも、ライブラリ(npm/pip/RubyGems/Maven等)の方がコード量で圧倒的に多くなりがちです。そのライブラリも、さらに別のライブラリに依存しています。

つまり、依存はピラミッド構造で広がっており、どこか1段が悪意を持つだけで上層まで影響が及びます。これが現代の最も深刻な攻撃面の一つです。

ここで効いてくるのが『信頼の連鎖』という考え方です。あなたが直接選んだライブラリは、たぶん信頼できるものでしょう。でも、そのライブラリが裏で使っている“孫ライブラリ”“ひ孫ライブラリ”まで、あなたは選んでいません。なのに、それらのコードはあなたのアプリの中で同じ権限で動く。つまり“顔も知らない誰か”を、無条件で家に上げているようなもの。直接の知り合いだけでなく、その先までが運命共同体——これがサプライチェーンの本質です。

まず、規模感を実感してください。今どきのアプリは、自分が手で書くコードはほんの一部。残りの大半は、npmやpipで入れた“他人が書いたライブラリ”です。しかもそのライブラリが、また別のライブラリを呼び、それがさらに別を呼び……と、気づけば数百〜数千のパッケージに支えられている。あなたのアプリは、巨大な“他人のコードの山”の上にちょこんと乗っている——まずこのイメージを持つことが出発点です。

図解:自分のコード vs 依存ツリー全体

見える自分のコードはピラミッドの先端で、その下に大量の依存パッケージが積み重なっている図
依存はピラミッド構造。下層のどこか1つが悪意を持つと上層まで波及する。

見える自分のコードはピラミッドの先端で、その下に大量の依存が積み重なっています。攻撃者はこの下層を狙います。

レストランの仕入れ先のどこかで混ぜ物をされ、最終料理まで影響するたとえ図
仕入れ先のどこかで混ぜ物をされると最終料理まで影響。サプライチェーン攻撃も同じ。
🍱 たとえるなら、食材の流通網

レストランで使う食材は、ほとんどが他社からの仕入れです。仕入れ先のさらに仕入れ先まで遡ると、世界中の小さな業者まで連なっています。もしどこか1ヶ所が混ぜ物を混入させたら、たとえ自分の店で丁寧に調理しても、お客さまに届く料理は安全とは言えなくなります。サプライチェーン攻撃は、まさにこの『流通網』を狙う攻撃です。

ここで覚える用語:SBOM
Software Bill of Materials の略。アプリが依存しているライブラリの一覧を、機械的に管理できる形式(SPDX/CycloneDX)で記述したものです。脆弱性が公開されたとき『自分のシステムが影響を受けるか』を素早く判定するための土台になります。

『SBOM』も難しそうな略語ですが、要は“材料表”です。食品のパッケージ裏に原材料が全部書いてあるように、「このアプリは、どのライブラリの、どのバージョンを使っているか」を一覧にしたもの。これがあると、たとえば「あるライブラリに重大な穴が見つかった!」というニュースが出たとき、“うちは使ってる?どこで?”を数分で調べられます。逆に材料表がないと、全部を手で探し回るハメに。いざという時の対応スピードが、まるで変わってくるんです。

サプライチェーン攻撃の3パターン

攻撃の手口は、大きく3つ。『本物そっくりの偽名で公開(タイポ狙い)』『社内パッケージと同名を外部に置いて取り違えさせる』『正規ライブラリ自体を乗っ取って毒を仕込む』。一つ目は、たとえば reqeusts(本物は requests)のような“打ち間違いを待つ罠”。うっかり入れた瞬間、悪意のコードがインストール時に走る——なんてことが起こります。

代表的な手口

typosquatting・dependency confusion・悪性アップデートの3パターンを示したカード型インフォグラフィック
①typosquatting ②dependency confusion ③悪性アップデート。守りはlockfile+自動スキャン+SBOM+信頼レジストリ。
  • typosquatting:本物に似た名前(reacct など)で偽パッケージを公開し、タイポした人をだます
  • dependency confusion:社内プライベートパッケージと同名の悪性パッケージをパブリックに公開、優先順位の隙を突く
  • 悪性アップデート/メンテナ乗っ取り:正規ライブラリが乗っ取られ、新バージョンに悪意のコードが混入(event-streamなど)

近年話題になったLog4Shell(Apache Log4j)のような事例では、攻撃の入口は『あるライブラリの脆弱性』そのものでした。発見時にどれだけ素早く対応できるかが、被害規模を左右します。

Log4Shellは、この“依存の怖さ”を世界中に知らしめた事件でした。Log4jという、ほぼ全てのJavaアプリが使っていると言っていいほど普及したライブラリに、深刻な穴が見つかった。すると世界中の開発者が一斉に「うちは使ってる?どのバージョン?」と大慌てで調べ回ることに。問題は脆弱性そのものより、“自分がそれを使っているかすら、すぐには分からなかった”こと。だからこそ、ふだんから材料表(SBOM)を持っておくことが、いざという時の生命線になるんです。

練習は、自分のプロジェクトが“どれだけの他人のコードに乗っているか”をのぞいてみることです。依存ツリーを出力すると、想像の何倍もの数に驚くはず。あわせて、既知の脆弱性スキャン(Dependabotなど)をかけて、危ない依存がないか確認します。攻撃ではなく健康診断。自分のリポジトリの中だけで、安心して試せます。

CTFでやってみよう:依存ツリーを点検

やってみよう / 自分のプロジェクトのみ

自分のリポジトリで、依存関係を可視化しよう

目的は実際の攻撃ではなく、『自分のアプリがどれだけのパッケージを使っているか』を可視化することです。

  1. パッケージマネージャ(npm/pip/yarn/bundler等)で list --depth=all 系コマンドで依存ツリーを出力する
  2. lockfile(package-lock.json / poetry.lock 等)がコミットされているか確認
  3. GitHub Dependabot や Snyk 等で既知脆弱性のスキャンを実行する
  4. 主要パッケージのメンテナ・最終更新日を確認し、放置気味のものを把握
  5. 可能ならSBOM(CycloneDX等)を出力し、CIに組み込む
他者のリポジトリ・パッケージレジストリへの悪意ある操作は絶対にやめてください。確認は自分のプロジェクトの範囲だけです。

守りについては、最初に“心構え”を一つ。

他人のライブラリの中身まで、全部チェックするのは無理じゃない?

その通りで、完全な事前チェックは現実的に不可能なんだ。だから発想を“防ぐ”から“素早く気づいて、素早く切り替える”にずらす。具体的には、①バージョンをlockfileで固定して勝手に変わらないようにし、②自動スキャンで危ない依存に常時アンテナを張り、③SBOM(材料表)で“どこで何を使っているか”を見える化しておく。そうすれば、悪いニュースが出ても「うちはここだけ、すぐ直そう」と動ける。“ゼロにする”より“最短で対応できる体制”が、この分野の現実解だよ。

守る側なら、「lockfile固定+自動スキャン+SBOM」

サプライチェーン攻撃の守りは、「lockfileでバージョン固定」「CIで自動スキャン」「SBOMで把握」「信頼レジストリへ集約」が中心です。完全防御は難しい領域ですが、検知と切替を素早く行うための準備は不可欠です。

守るための基本チェック
  • lockfileをコミットし、本番ビルドは固定バージョンでインストール
  • CIでDependabot / Snyk / npm audit 等の脆弱性自動スキャンを実施
  • SBOM(SPDX/CycloneDX)を生成し、脆弱性公開時に影響範囲を即時判定
  • 社内プライベートパッケージはscope/名前空間で保護し、dependency confusion対策を行う
  • 新規依存追加時はレビュー必須(メンテナ・ライセンス・更新頻度を確認)
  • 本番デプロイ前に依存ハッシュ検証(npm --integrity等)で改ざんを検出

『自分のコードだけ』を守るだけじゃ足りないんだね。

そう。依存ツリーは自分の延長として扱うのが現代の常識。SBOMで見える化しておけば対応速度が違うよ。

ここまでをひと言で言うと、サプライチェーンの守りは『依存も自分のコードだと思って運用する』。他人が書いたものでも、自分のアプリで動く以上、責任は自分側にあります。だから、バージョンを固定し、材料表を持ち、常にスキャンする。“入れっぱなしで放置”をやめるだけで、リスクはぐっと下がります。

まとめ:『依存も自分のコード』として運用する

今回のポイント
  • 現代のアプリはピラミッド構造で大量の依存に乗っている
  • 3型はtyposquatting・dependency confusion・悪性アップデート
  • 守りはlockfile固定+自動スキャン+SBOM+信頼レジストリ
  • 『発見時にどれだけ早く動けるか』が被害を左右する

今日の持ち帰りは『材料表を持ち、いつでも更新できる体制を作る』です。サプライチェーン攻撃は、完全には防げません。でも、自分が何に依存しているかを把握し、危険が分かったらすぐ差し替えられる準備さえあれば、被害は最小限に抑えられます。“ゼロリスク”ではなく“即応できる強さ”——それが、この領域のゴールです。

次回は、APIアクセスを支えるAPI認証を扱います。JWT・OAuth・APIキーが破られる時と、その守り方を見ていきましょう。

次に読みたい記事

参考資料

記事URLをコピーしました