開発しているソフトウェアにどのようなOSS何が組み込まれているか、本当にご存じですか。
今やオープンソースは、自社開発コードベースやコミュニティプロジェクトなど、至るところにあります。組織においては、オープンソースコードを使っているか否かが問題なのではなく、どのオープンソースコードをどれくらい使っているかが重要なのです。ソフトウェアサプライチェーンの内容を認識していなければ、いずれかの依存関係における上流の脆弱性がアプリケーションに影響を及ぼし、セキュリティ侵害を受ける可能性が高くなります。この記事では、“ソフトウェアサプライチェーンのセキュリティ”の意味を深く掘り下げ、それがなぜ重要であるか、そしてプロジェクトのサプライチェーンのセキュリティをいかに強化できるかを見ていきます。
ソフトウェアサプライチェーンとは、ソフトウェアに影響するすべてのものを指す
従来、サプライチェーンとは、製品を提供するために必要なもの(使用されるすべてのコンポーネントも含む)を表す用語です。店に並ぶチョコレート菓子を例に挙げると、原材料リスト、パッケージ、栄養成分に関する情報に加え、場合によってはオーガニック原材料や製造施設に関する情報なども含まれます。それだけではなく、製品の輸送にかかわることも含まれています。
チョコレートの例をコードベースに置き換えてみましょう。ソフトウェアサプライチェーンとは、開発からCI/CDパイプラインを経由し、実稼働環境に配備されるまで、コードに組み込まれる、あるいはコードに影響するすべての要素を指します。
コード、バイナリ、その他のコンポーネントなど、ソフトウェアに組み込まれるすべてのもの、それらのソース(リポジトリ、パッケージマネージャーなど)といった、ありとあらゆるものを意味します。ソフトウェアサプライチェーンには、ソフトウェアを記述した人、提供されたタイミング、セキュリティの問題をレビューした方法、既知の脆弱性、サポートされるバージョン、ライセンス情報など、どこかの段階でソフトウェアに関与したものがすべて含まれます。さらに、単一のアプリケーションにとどまらず、ビルドやパッケージングスクリプト、またはアプリケーションが実行されるインフラストラクチャを稼働するソフトウェアなど、スタックの他の部分も網羅します。また、ソフトウェアの実行によるリスクを判断する際に役立つ、ソフトウェアについての情報も含まれます。
ソフトウェアサプライチェーンのリスクは依存関係から継承される
セキュリティという点でソフトウェアサプライチェーンが重要なのはなぜでしょうか。現在、ソフトウェアの依存関係は広範囲にわたっています。プロジェクトにおいて、自分が機能を完全に記述していないオープンソースの依存関係が、数百個単位で使われることも珍しくありません。平均すると、その数はリポジトリあたり203個に及びます。業界データによると、コードベースの99%にオープンソースコードが含まれており、企業のコードベースの85~97%でオープンソースが使われていることがわかっています。すなわち、アプリケーションの大半は、自分が記述していないコードで構成されているということです。サードパーティまたはオープンソースの依存関係における脆弱性とは、おそらく自分が記述したコードほど厳密な管理ができない点であり、これによって潜在的なセキュリティリスクが大きくなります。
このような依存関係の中に弱点があれば、脆弱性も存在する可能性があります。ここで恐ろしいのは、自分が知らない間に依存関係が変わることがある点です。現在の依存関係に脆弱性があり、それがアプリケーションで悪用できない場合でも、コードベースの内側や外側に変更が加えられることによって将来的に影響を受けやすくなる可能性もあります。数千人ものオープンソース開発者の作業を活用するということは、数千人もの他人が自分の実稼働コードにコミットアクセス権を持つことを意味します。そのため、パッチを適用していない脆弱性、悪意のない誤り、サプライチェーンの依存関係への悪意ある攻撃が、大打撃となるおそれがあります。
サプライチェーンのセキュリティ侵害は現実にあるがレアケースである。問題の元凶はパッチを適用していないソフトウェア
ソフトウェアサプライチェーンへの攻撃は、コンポーネントに悪意あるコードが意図的に付加され、そのコンポーネントのサプライチェーンを利用してコードをターゲットに配布することで発生します。サプライチェーンへの攻撃は現実に起きます。サプライチェーンの攻撃にはいくつかの方法があります。悪意あるコードを新しいコミッターとして直接挿入する方法から、他者に気づかれることなくコミッターのアカウントを乗っ取る方法、あるいは署名キーを侵害して、本来はコンポーネントの一部ではないソフトウェアを配布する方法などが挙げられます。しかし、ソフトウェアサプライチェーンそのものが最終的なターゲットになることはめったにありません。クリプトマイニングのためにマルウェアを挿入したり、ボットネットアクセスのためにバックドアを挿入したりするチャンスを手に入れることが攻撃の理由です。
ソフトウェアサプライチェーンへの攻撃は依然として少なく、(我々が知る限り)年に数十件未満です。また、国家がエネルギー部門の企業に攻撃を仕掛けるなど、標的が絞られている傾向もあり、広範にわたる危険性はありません。今日に至るまで、オープンソースセキュリティへの広範囲にわたる攻撃はほとんど発生していません。
おそらく、ソフトウェアサプライチェーン攻撃の中でも特に有名な例は「event-stream」のインシデントでしょう。event-streamとは、npm経由で幅広く使われているNode.jsライブラリです。2018年の秋に、新しいユーザーがGitHubでevent-streamを引き継ぐことになりました。作者は援助を喜んで受け入れ、そのユーザーに公開権限まで付与しました。数週間後、新ユーザーはevent-streamに新しい依存関係である「flatmap-stream」を追加しました。その翌週、同じユーザーが、「flatmap-stream」依存関係を使わなくても済むようコードを書き換え、削除を試みました。変更はコードベースで行われましたが、あいにく、npm上でライブラリがホストされている場所までプッシュされませんでした。10月に、別のユーザーが「flatmap-stream」にマルウェアを混入しました。その後、「event-stream」を使用して、最新バージョンの「flatmap-stream」をプルしたユーザーにマルウェアが送信されるようになりました。ここで強調しておきたいのは、ライブラリ作者を責めてはならないことです。オープンソースプロジェクトに取り掛かっていれば、人の手を借りたくなるのは当然のことだからです。
パッチを適用していないソフトウェア
「event-stream」のようなサプライチェーンへの直接的な攻撃はめったにありませんが、パッチを適用していないソフトウェアは頻繁に見かけます。今日の企業ではオープンソースが多用されており、これからも減少することはないでしょう。まさに「Open source has won(オープンソースが勝利を得た)」です。オープンソースソフトウェアの使用は(当然のことながら)なくなることはないため、今日のサプライチェーンのセキュリティを脅かすのはパッチが適用されていないソフトウェアなのです。この点を把握したうえで、プロジェクトの依存関係に脆弱性が潜むリスクにどのように対処できるでしょうか。
幸いにも、オープンソースの脆弱性の85%については、パッチがすでに提供されていると推定されるため、パッチを適用さえすればセキュリティを確保できます。しかし、プロアクティブであることと、ソフトウェアサプライチェーンの脅威に効果的に対処することには、パッチを適用する以上のことが必要になります。DevSecOpsを導入するということは、ソフトウェア開発における継続的な作業の1つとしてセキュリティにアプローチする必要があることを意味します。すなわち、自分が使用している依存関係を定期的に把握し、依存関係における脆弱性を知り、パッチを適用したうえで、作業に戻ることが求められるのです。開発者としては、次のような能力が必要となります。
- 開発中のソフトウェアに組み込まれているものを把握する。そのためには、推移的な依存関係を含む依存関係を特定することが必要です。また、脆弱性やライセンス制限など、依存関係に伴うリスクも理解しておく必要があります。
- 依存関係を管理する。新しいセキュリティ脆弱性が発見されると、まず、自分が影響を受けるかどうかを確認する必要があります。影響を受ける場合はアップデートし、最新機能とセキュリティパッチを入手します。新しい依存関係を生じさせる変更をレビューし、不要な依存関係を定期的に取り除くことで、依存関係を維持します。
- サプライチェーンを監視する。コントロールを監査して依存関係を管理し、最終的には監査から適用へと移行することで、サプライチェーンのずれを防ぐ必要があります。
私たちは、ソフトウェアサプライチェーンのセキュリティを確保する道のりに踏み出したばかりですが、依存関係にパッチを適用すること以上に期待できることがあります。サプライチェーンの信頼性向上への取り組みの中で、業界が目指している理想があります。これには、整合性の確保と、プロブナンスの検証などが含まれます。「サプライチェーンの整合性」とは、コンポーネントが記述どおりのものであることを確認することです。すなわち、チョコレートの包装紙に記されている原材料をそのまま信じてもかまわないという意味です。これは、再現可能なビルドを使用するなどの方法で実現できます。「プロブナンスの検証」とは、特定のコンポーネントがどこで作成されたかを把握することです。これによって、署名済みのビルドや透明性ログなどを使用して、コンポーネントのプロバイダーやそのコンポーネントのメタデータのプロバイダーを信頼できるようになります。これらは、ソフトウェア部品表(SBOM)のコンセプトに密接に関係しています。チョコレートのメーカーが提供する検証済みの原材料リストのような、ソフトウェアのコンポーネントのリストが作成されます。
GitHubが提供するソフトウェアサプライチェーンのセキュリティ対策機能
私たちは、開発者、メンテナー、企業、研究者が世界のソフトウェアをセキュリティ保護できるよう、率先して取り組むことを目標として掲げています。そのためには、ソフトウェアをセキュリティ保護するために必要なツールをオープンソースコミュニティが取得できるよう投資し、開発者や企業が依存関係を容易に管理できるようにしていきます。
開発者としての第一歩は、依存関係を理解し、保守することです。これは通常、「ソフトウェア構成分析(SCA)」で達成できます。SCAとは、使用する依存関係を決定し、依存関係における脆弱性を特定し、パッチを適用するための一連のツールのことです。すなわち、ここまでに説明してきたこととまったく同じことです。GitHubでは、以下の機能によってSCAの機能を提供しています。
- 依存グラフは、すべての上流の依存関係と、リポジトリまたはパッケージのパブリックな下流の依存関係を特定します。プロジェクトの依存関係に加え、検出された脆弱性を依存グラフで確認できます。
- Dependabotアラートは、依存グラフやGitHub Advisory Databaseにおいて新たに検出された脆弱性の影響を受けるリポジトリを通知します。
- Dependabotセキュリティアップデートは、既知の脆弱性を解決できる最小バージョンに依存関係をアップデートするために、Dependabotからユーザーに送信されるPull Requestです。Dependabotバージョンアップデートも、設定したスケジュールに従って依存関係の新しいバージョンをチェックし、アップデートを提案します。
まとめると、ソフトウェアサプライチェーンとは、コードに組み込まれる、またはコードに影響するすべてのものです。サプライチェーンのセキュリティ侵害は現実に起きており、依然としてレアケースではありますが、発生頻度は高くなっています。そのため、サプライチェーンを保護するために最も重要なのは、脆弱性にパッチを適用することです。ソフトウェアサプライチェーンを効果的にセキュリティ保護するために、環境の依存関係を理解し、その依存関係における脆弱性を知り、それらにパッチを適用する必要があります。GitHubネイティブのSCA機能を有効にすることで、依存グラフ、Dependabotアラート、Dependabotセキュリティおよびバージョンアップデートにより、依存関係の管理とパッチ適用の面倒な作業を自動化できます。