Overview
依存関係管理(Dependency Management)とは、ソフトウェア開発において使用するサードパーティのライブラリ、パッケージ、フレームワークなどの外部コンポーネントを安全に選定・導入・更新・監視するプロセスです。現代のソフトウェアはオープンソースコンポーネントに大きく依存しており、一般的なアプリケーションのコードベースの70〜90%がオープンソースの依存関係で構成されています。この依存関係の安全性を確保することは、ソフトウェアサプライチェーンセキュリティの根幹をなします。
近年、Dependency Confusion攻撃やタイポスクワッティングなど、パッケージマネージャーの仕組みを悪用した攻撃が急増しています。攻撃者は正規のパッケージに似た名前の悪意あるパッケージを公開レジストリに登録したり、組織のプライベートパッケージと同名のパッケージを公開して優先的にインストールさせたりする手法を用います。これらの攻撃は、ビルドパイプラインの中で自動的に実行されるため、検知が極めて困難です。
安全な依存関係管理には、ロックファイルの厳格な管理、プライベートレジストリの活用、SLSA(Supply-chain Levels for Software Artifacts)フレームワークに基づくプロベナンス検証、Sigstoreによるコード署名の検証など、多層的なアプローチが必要です。開発者だけでなく、CI/CDパイプライン全体を通じた包括的な依存関係セキュリティ戦略が求められています。
Details
Dependency Confusion攻撃
Dependency Confusion(依存関係かく乱)攻撃は、組織が内部で使用するプライベートパッケージと同名のパッケージを公開レジストリ(npm、PyPI、RubyGemsなど)に登録することで、ビルドシステムに悪意あるパッケージをインストールさせる攻撃手法です。多くのパッケージマネージャーは、プライベートレジストリよりも公開レジストリを優先する、またはより高いバージョン番号を優先するという挙動があり、この仕組みが悪用されます。
攻撃者は対象企業のプライベートパッケージ名を特定するために、GitHubリポジトリの設定ファイル、エラーメッセージ、求人情報に記載された技術スタックなどから情報を収集します。発見した名前で公開パッケージを作成し、インストール時に実行されるスクリプトに悪意あるコードを仕込むことで、ビルドサーバーやCI/CD環境を侵害します。
タイポスクワッティング
タイポスクワッティングは、正規のパッケージ名に似た名前(タイプミスを狙った名前)で悪意あるパッケージを公開する手法です。たとえば「lodash」の代わりに「l0dash」や「loadsh」、「colors」の代わりに「colour」など、開発者が誤ってインストールする可能性のある類似名を使用します。
この攻撃は特にnpmエコシステムで多発しており、数百万のパッケージの中に紛れ込むため発見が困難です。悪意あるパッケージは、正規パッケージの機能をそのままコピーした上でバックドアを追加することが多く、インストール後も正常に動作するため、開発者が気づきにくいという特徴があります。
ロックファイルセキュリティ
ロックファイル(package-lock.json、yarn.lock、Pipfile.lock、Gemfile.lockなど)は、依存関係のバージョン、取得元URL、整合性ハッシュを固定するための重要なセキュリティ機構です。ロックファイルを使用することで、異なる環境やタイミングでのビルドでも同一の依存関係がインストールされることが保証されます。
しかし、ロックファイルの改ざんや意図的な操作(ロックファイルポイズニング)も攻撃ベクトルとなります。攻撃者がプルリクエストを通じてロックファイルを変更し、依存関係の取得先を悪意あるレジストリに書き換えるケースが報告されています。コードレビューにおいてロックファイルの差分を注意深く確認し、CI/CDパイプラインでの整合性チェックを自動化することが重要です。
プライベートレジストリとスコーピング
組織内部のパッケージを安全に管理するためには、プライベートレジストリ(Artifactory、Nexus、GitHub Packages、AWS CodeArtifactなど)の導入が不可欠です。プライベートレジストリを使用し、名前空間(スコープ)を適切に設定することで、Dependency Confusion攻撃のリスクを大幅に低減できます。
npmでは@organization/package-nameのようなスコープ付きパッケージを使用し、.npmrcファイルでスコープごとのレジストリマッピングを明示的に設定することが推奨されます。また、プロキシレジストリを介して公開パッケージをキャッシュ・検証する仕組みを導入し、承認済みパッケージのみが開発環境で利用可能となるようガバナンスを確立しましょう。
SLSAフレームワークとプロベナンス検証
SLSA(Supply-chain Levels for Software Artifacts)は、Googleが提唱したソフトウェアサプライチェーンの完全性を保証するためのフレームワークです。SLSAはレベル1からレベル4までの成熟度モデルを定義し、ビルドプロセスの文書化、ビルド環境の隔離、ソースコードと成果物の紐付け(プロベナンス)の検証を段階的に求めます。
プロベナンス情報には、ビルドに使用されたソースコードのコミットハッシュ、ビルド環境の詳細、ビルドステップの記録などが含まれます。パッケージの消費者は、このプロベナンス情報を検証することで、パッケージが信頼できるソースから改ざんなくビルドされたことを確認できます。
Sigstoreによるコード署名
Sigstoreは、ソフトウェアの署名と検証を簡素化するオープンソースプロジェクトです。従来のコード署名はPGP鍵の管理が煩雑でしたが、Sigstoreはキーレス署名(OIDC認証に基づく短命の証明書を使用)を実現し、開発者が容易にパッケージに署名できるようにしました。
Sigstoreのエコシステムは、署名ツール(Cosign)、透明性ログ(Rekor)、証明書発行(Fulcio)の3つの主要コンポーネントで構成されます。npm、PyPI、Maven Centralなどの主要レジストリがSigstoreの署名検証に対応しつつあり、依存関係の真正性を検証する標準的な仕組みとして普及が進んでいます。
Security Measures
- 01プライベートレジストリとスコープ設定の徹底:組織内部のパッケージには必ず名前空間(スコープ)を使用し、プライベートレジストリを導入してください。パッケージマネージャーの設定ファイル(.npmrc、pip.conf等)でスコープごとのレジストリマッピングを明示的に指定し、Dependency Confusion攻撃を防止しましょう。
- 02ロックファイルの厳格な管理と検証:ロックファイルを必ずバージョン管理に含め、CI/CDパイプラインでは--frozen-lockfile(npm ci、yarn --frozen-lockfile等)オプションを使用して、ロックファイルと一致しない依存関係のインストールを拒否してください。プルリクエストでのロックファイル変更は特に注意深くレビューしましょう。
- 03依存関係のSCA(Software Composition Analysis)スキャン:Snyk、Dependabot、Renovate、Trivy等のSCAツールをCI/CDパイプラインに統合し、既知の脆弱性を持つ依存関係を自動検出してください。セキュリティアドバイザリに基づく自動プルリクエスト生成を有効化し、脆弱な依存関係の迅速な更新を実現しましょう。
- 04SLSA準拠のビルドプロセスとプロベナンス検証:SLSAフレームワークに沿ったビルドプロセスを構築し、成果物のプロベナンス(出自情報)を生成・公開してください。依存関係を導入する際は、プロベナンス情報を検証し、信頼できるソースから改ざんなくビルドされたことを確認しましょう。
- 05Sigstoreによる署名検証の導入:パッケージの真正性を保証するために、Sigstore(Cosign)による署名検証をCI/CDパイプラインに組み込んでください。署名のないパッケージや検証に失敗したパッケージのインストールを拒否するポリシーを段階的に導入しましょう。
- 06依存関係の定期的な棚卸しと最小化:SBOM(Software Bill of Materials)を生成して依存関係を可視化し、不要な依存関係を定期的に削除してください。直接依存だけでなく推移的依存関係(transitive dependencies)も含めて監視し、攻撃対象面を最小限に抑えましょう。
Incidents
📋 Dependency Confusion攻撃による大手企業35社への侵入(2021年)
2021年、セキュリティ研究者のAlex Birsan氏がDependency Confusion攻撃の手法を実証し、Apple、Microsoft、PayPal、Shopify、Netflix、Tesla、Uberなど35社以上の企業システムへのコード実行に成功しました。Birsan氏は各企業のGitHubリポジトリやJavaScriptファイルからプライベートパッケージ名を特定し、公開レジストリに同名の高バージョン番号パッケージを登録しました。
多くの企業のビルドシステムが公開レジストリの高バージョンを優先的にインストールしたため、Birsan氏が仕込んだDNSルックバックコードが企業のビルドサーバー上で実行されました。この研究はバグバウンティプログラムを通じて報告され、総額13万ドル以上の報奨金が支払われました。この事例をきっかけに、業界全体でDependency Confusion対策が急速に進みました。
📋 ua-parser-jsパッケージの乗っ取り事件(2021年)
2021年10月、週間800万ダウンロードを超える人気npmパッケージ「ua-parser-js」のメンテナーアカウントが乗っ取られ、暗号通貨マイナーとパスワード窃取マルウェアが仕込まれたバージョンが公開されました。悪意あるバージョンは3つのマイナーバージョン(0.7.29、0.8.0、1.0.0)として公開され、数時間で多数の開発者やCI/CDシステムによってインストールされました。
このパッケージはFacebook、Amazon、Google、Microsoftなど大手企業のプロジェクトでも使用されており、影響範囲は極めて広範でした。事件後、npmは二要素認証の義務化やパッケージ公開ワークフローの強化など、レジストリ全体のセキュリティ対策を強化しました。
📋 PyPIにおける大規模タイポスクワッティングキャンペーン(2023年)
2023年、PyPI(Python Package Index)において、人気パッケージの名前に酷似した数百の悪意あるパッケージが発見されました。攻撃者はrequests、beautifulsoup4、tensorflowなどの人気パッケージのタイプミスバリエーションを大量に登録し、インストール時にデータ窃取コードやバックドアを実行するよう仕込んでいました。
この攻撃は組織的に行われ、パッケージの説明文やREADMEを正規パッケージからコピーすることで信頼性を装っていました。PyPIは一時的に新規パッケージの登録を停止する措置を取り、パッケージ名の類似性チェックの強化やマルウェアスキャンの自動化など、レジストリの防御機能を大幅に強化しました。