2020 年 12 月、SolarWinds は同社の Orion 製品が大規模攻撃の標的となり、多数の政府機関を含む同社の多くの顧客のインフラストラクチャに攻撃者が侵入したことを公表しました。 この侵害が広範に及んだことから、サプライチェーンの脆弱性、そしてサードパーティの依存関係がソフトウェア システムのセキュリティに果たす役割に大きな注目が集まりました。 これらの攻撃に新種の脅威はなかったものの、この出来事によってこうした領域に対する関心は高まり、組織は次の標的にならないためにセキュリティ体制を強化しようと考えるようになりました。 皆さんのようなソフトウェア エンジニア チームとサプライ チェーンとの最も一般的なやり取りは、アプリケーションに組み込む外部ライブラリの選択です。 よく管理された外部ライブラリは、エンジニアの膨大な時間の節約という大きな恩恵を開発作業にもたらします。エンジニアは一般的な機能を再実装する必要性がなくなり、製品の主要な差別化機能に集中的に取り組むことができます。 一方、実装が不十分なライブラリは、使用が難しいことに加え、セキュリティの脆弱性をもたらして組織と顧客をリスクにさらす可能性があります。極端なケースでは、サービスと関係のない要素の動作を妨げたり、アーキテクチャ全体を弱体化させたりすることさえあります。 ここでは、私がライブラリのエンジニアリング プラクティスの健全性や、ライブラリがセキュリティにもたらしうる影響を評価する際の多くの考慮事項を紹介します。 これらのアプローチは、処方箋ではなく、開始点として提供するものです。 読者の皆さんはご自分のニーズに合ったアプローチを探してください。 この領域に特効薬はありませんが、プロジェクトに含まれる依存関係の質を高めれば、攻撃対象領域を大幅に削減し、製品の拡張や保守をより簡単に実施できるようになります。
ライブラリの規模
最初に考慮するのはライブラリの規模です。これは、どのくらい詳細な評価が必要 (適切) かを決定づけることから、重要な考慮事項です。 そのライブラリはどのくらいの機能を提供しますか? 製品が動作するために、その機能はどのくらい重要でしょうか? フットプリントが小さいシンプルなライブラリは、コードに緊密に統合される大規模フレームワークより評価精度を下げることができます。 重要な機能の場合には危険信号となる兆候の一部 (例:頻繁に更新されない) は、小規模ライブラリにとっては普通のこと、または起こりうることかもしれません。 確認すべきもう 1 つの事項は、ライブラリの使用方法です。 開発における依存関係 (静的分析ツールや、ユニット テスト フレームワークのコンポーネントなど) は、ランタイムの依存関係よりもリスクがはるかに少なくなります。 ビルド パイプラインに問題がある場合、リリース遅延が発生したり、開発者が他の問題に一時的に直面したりすることはありますが、ユーザーに直接影響が及ぶことはなく、通常はアプリケーション自体のセキュリティのリスクにはなりません。
メンテナンス履歴
プロジェクト全体の正常性を把握する最も簡単な方法は、ソースの管理履歴を確認することです。 最後のリリースはいつでしたか? リリースはどのくらい頻繁に公開されていますか? ソースコード リポジトリへのコミット レートはどのくらいですか? 私は頻繁に更新されているプロジェクトを好ましく感じます。頻繁に更新されていれば、ライブラリが今後も継続的に保守されるという確信が高まるからです。 一方、長い間更新されていないプロジェクトの場合、未対応のバグが含まれていたり、一般的な依存関係の新しいバージョンや言語ランタイム自体との間に互換性の問題が発生したりすることがあります。 ライブラリの変更ログを詳しく確認することも非常に重要です。 リリースごとに導入された変更がリリース ページに記載されていることも、 変更ログがソース コード リポジトリのトップ レベルのファイルである場合もあります。 この情報が容易に入手できなければ、それは大きな危険信号です。 私は、1 つのリリースから次のリリースへの変更が明確に記載されていること、すべての下位非互換性が明確に文書化されていることを確認します。 ただし、下位互換性のない変更やコア機能のバグ修正が頻繁に行われている場合は、それ自体が懸念材料になります。リリースの前に、開発者が変更の計画やデバッグを十分に行っていないことを物語っているからです。
保守担当者との関係
より掘り下げた評価を実施する場合は、プロジェクトの課題トラッカーやその他の公的なコミュニケーション チャネルを確認することがあります。 保守担当者はユーザーにどのくらい迅速に対応していますか? ユーザーに対して親切で、フィードバックを受け入れる姿勢がありますか? それともけんか腰になりがちでしょうか? 未解決の問題と解決済みの問題の割合はどれくらいですか? 保守担当者はユーザーの懸念に積極的に対応していますか? それともバグレポートは長期にわたって休止されたままですか? ドキュメンテーションは包括的ですか? 実装のベスト プラクティスにユーザーを効果的に導いていますか? そのプロジェクトの周囲に活気あるコミュニティが存在していますか? たとえば、ユーザー サポートの負担をメインの保守担当者だけが負っていますか? それとも他のコミュニティ メンバーが、サポートの行き届かない部分に積極的に対応していますか? コミュニティと健全な関係を維持できるプロジェクトは、ユーザーの個別のニーズを満たし、変化する環境に迅速に適応できる可能性が大幅に高くなります。
推移的依存関係
この評価を実施するには、単にリリースの頻度を数えるよりも若干多くの作業が必要になりますが、情報の宝庫を得ることができます。 最初に理解したいのは、1 つのライブラリが依存する追加の依存関係の数です。特に、無駄な依存関係を取り込んでいないかどうかです。 ライブラリに重要な機能を提供する依存関係には、関連のないタスクに多くの追加ライブラリを取り込む依存関係のような懸念はありません。 依存関係は、1 つ追加されるたびに複雑さとサプライ チェーンのリスクが増加します。 懸念がある場合は、ドッカー コンテナに該当のライブラリをインストールし、そのプロセスでいくつの追加ライブラリが付加されるかを数えれば、簡単に評価できます。 このカテゴリでの最大の懸念は、新しい脆弱性が検出されたときにいかに簡単に依存関係を更新できるかです。 この理由から、これを評価するのに最も重要な確認事項は、依存関係が制約的 (ライブラリの特定のバージョンによってのみ満たされる) か、許容的 (バージョンの範囲によって満たされる) かということです。 制約的な依存関係は大きな懸念になります。パッチの適用が難しくなったり、他の機能を利用するために依存しているライブラリのダウングレードを強制されたりする可能性もあるためです。 また、これらの推移的依存関係の新しさも重要です。 2 か月前のリリースを指定するバージョンの依存関係は、2 年前のリリースを指定する依存関係よりも懸念がはるかに小さくなります。 これと同様に、安定したプロジェクトであることの証の 1 つは、頻繁に更新が行われて依存関係が最新の状態に保たれていることです。
言語間依存関係
ある言語で記述され、他の言語との間に追加の依存関係を持つパッケージ (たとえばコンパイル済みの C 拡張子を持つ Python ライブラリ) には特に注意が必要です。 副次的な依存関係に、自分が得意としない言語またはプログラミング環境が関与している場合は、その総合的な品質の評価が難しくなります。 さらに、異なる言語ではパッケージの規則が異なることが多く、言語が混在するプロジェクトの保守担当者は運用するすべてのプログラミング言語のベスト プラクティスに精通していないことが多いため、パッチの適用や更新がさらに難しくなります。
暗号化ライブラリ
暗号化ライブラリは、アルゴリズムの複雑さや暗号化領域の脆弱性がもたらしうる影響の大きさを考えると、特別な考慮が必要です。 これらのライブラリは特に入念に検証し、長い実績を持つ徹底的に検証されたライブラリのみを使用するようにしてください。 安全な選択肢の例としては、OpenSSL (C および C++)、BouncyCastle (Java)、PyCA 暗号化ライブラリ (Python) が挙げられます。 ライブラリの選択は、自社のセキュリティ ポリシーやコンプライアンス要件によって制限されることがあります。 暗号化ライブラリの既知の脆弱性に注意し、常に新しいリリースに関する最新情報を入手するようにしてください。 サードパーティの依存関係の中で、セキュリティに最大の影響をもたらすのがこの依存関係です。
コードとドキュメンテーションの品質
これ以降のセクションの評価は多くの労力を必要としますが、リスクが高いケースではこのレベルでの調査が必要になることがあります。 コード全体の品質を知りたいとき、私は自分が既に詳しく理解している機能を使用するソース コードを見つけて、コード ベース内のこの小さい領域の出来栄えを評価します。 または、プロジェクトのドキュメンテーションの品質を確認し、作成者の明確さ、そして複雑な概念を効率的に伝達する能力に焦点を当てることもあります。 どちらの場合も目的は、保守担当者が詳細に気を配っているか、手抜きする傾向にあるかを見極めることです。 つまり、プロジェクトの一部分に気配りが行き届いていれば、全体にもその傾向が当てはまるだろうと期待します。 具体的な例として、ある Python プロジェクトの SSL 処理を調査する場合、私なら次のことを確認します。
- 既定の SSL 接続パラメーターを使用しているか、安全性を高めるためにパラメーターをカスタマイズしているか?
- カスタマイズを行っている場合、どのくらい思慮深い変更を行っているか?
- ユーザーに追加のカスタマイズを許可しているか?
- カスタマイズを許可している場合、Python 標準ライブラリの SSLContext オブジェクトを再利用するか、一から作り直しているか?
このような場合に私が評価するのは、健全な設計原則があること、標準イディオムを再利用していること、作成者がユーザーの潜在的なニーズを予測してそれに対応する適切な拡張性を提供していることです。
脆弱性への対処
この要素は最後に取り上げましたが、その理由は、通常はこの点についての印象を得るまでに時間がかかること、また最初の評価ではあまり有効ではない場合があることです。 また脆弱性への対処は、ライブラリがどのくらい幅広く利用され、どのくらいセキュリティと関連しているかによっても大きく異なります。 しかし、この要素は既存のライブラリを継続して使用するか、別のライブラリへの移行を試すかを決定する要因になります。 簡単に言うと、私はプロジェクトの保守担当者が脆弱性のパッチ適用にどのくらい迅速に対応するか、私たち自身の環境内でこれらのパッチをどのくらい簡単に適用できるかの評価を試みます。 頻繁に脆弱性を公開するプロジェクトには若干懸念がありますが、その理由はコード全体の品質やとメンテナンス プラクティスというよりは、幅広く使用されていることやセキュリティとの関連性である可能性があります。 もっと適切な基準は、脆弱性が公開された後の対応です。 パッチは即座に新しいリリースに組み込まれていますか? パッチ適用済みのバージョンのリリース後、簡単にアップグレードできますか? プロジェクトが頻繁に全面的な変更を行う場合 (特にたびたび下位互換性が失われる場合)、旧バージョン用に修正プログラムをバックポートしていますか? ライブラリが Linux ディストリビューションの一部である場合、旧バージョン用のパッチのバックポートは、元の開発者ではなくディストリビューションの保守担当者の責任となりますが、上記の質問はパッケージ作成者のライブラリ処理方法にも当てはまります (ディストリビューションでは多くの場合、アクティブなメンテナンスを行うコア パッケージと、アップストリーム リリースを追跡して最小限の変更を適用する、より周辺的なパッケージが区別されます)。 ライブラリがこれまで脆弱性に適切に対処していないことが明らかな場合や、セキュリティ パッチの適用が難しい方法で運用されている場合、私はチームに対して他のライブラリに移行するように推奨します。
結論
ソフトウェア プロジェクトの総合的な品質と、それを取りまくコミュニティを評価するスキルは非常に重要であり、ソフトウェア プロジェクトの相互依存が進むにつれてその重要性はさらに高まるでしょう。 これは非常に個人的なスキルでもあります。多くの場合、自分の専門分野に関するライブラリの保守担当者の意思決定を調査することで、最大の価値を得ることができます。 使用する可能性があるサプライヤーの詳細を逐一完全に検証するのは、自分で機能を構築することよりも難しい作業です。そのため評価プロセスは、ある程度の信頼を確立し、誤った相手を信頼しないために講じる手段の 1 つになっています。 最終的に、サードパーティの依存関係の入念な評価方法を学習することは、自社製品のセキュリティと信頼性に責任を持つエンジニアリング文化を構築する重要な要素となります。
著者について
Jacob Emmert-Aronson は、Webex Intelligence 部門 Mindmeld チームのシニア エンジニアです。 Jacob は情報セキュリティ、DevOps、ソフトウェア メンテナンスの知識リーダーであり、これらのトピック同士の関連性を理解することを得意としています。
MindMeld チームへの参加にご興味がある方は、 mindmeld-jobs@cisco.com にメールでご連絡ください
Webex にサインアップ弊社のホームページをご覧いただくか、サポートが必要な場合は直接お問い合わせください。 Webex のサービスの詳細を見るか、無償アカウントにサインアップする場合は、こちらをクリックしてください。