Node.jsに実験的な整合性ポリシーを導入
2019年3月21日
0 分で読めます整合性ポリシーを導入する実験的な機能が、Node.js 11.8.0のコアに最近追加されました。まだLTS版には搭載されていないこの機能は、モジュールの読み込み時にNode.jsランタイムの整合性を検証し、モジュールのコードが改ざんされていないことを確認します。
Bradley Fariasは2018年10月にこの変更を提案しました。ブラウザーにある同様のセキュリティ機能、Subresource Integrityから着想を得ています。
Subresource Integrity
World Wide Web Consortium(W3C)は、HTML文書内のサブリソースを検証できるようにする新しいintegrityフィールドをHTML仕様に提案しました。Webページでは、scriptタグやlinkタグを使ってブラウザーにリソースを読み込ませることができます。しかし、こうしたHTML要素でintegrityフィールドを使用しない限り、リソースが改ざんされていないかを検証する方法はありません。
Webページは、自サイトまたはサードパーティーのリソースをリモートサーバーから読み込みます。その際、最も一般的に使われるのがコンテンツデリバリーネットワーク(CDN)です。こうしたリソースを読み込むとき、リソースファイルの整合性を検証することで、悪意ある攻撃者から保護できます。たとえば、次のようなケースが考えられます。
侵害されたリモートサーバーが、変更されたリソースファイルを配信する
転送経路が侵害され、リソースファイルが改ざんされる
Node.jsモジュールの整合性ポリシー
ブラウザーのセキュリティ機構によるリソース整合性の強制に着想を得て、Node.jsでも同じように、プログラムコードがサードパーティーモジュールを要求した際に、メモリーに読み込んで実行する前に整合性を検証できるとしたらどうでしょうか。
Node.js 11.8.0の新しい実験的なポリシー機能では、コマンドラインフラグ--experimental-policyを使ってこの動作を強制できます。このフラグには、プロジェクト内のすべてのリソースを記述したポリシーマニフェストを指定します。仕組みを見てみましょう。
Node.jsのポリシーマニフェスト
11.8.0ではモジュールローダーによる強制機能のみが提供されていますが、Node.jsは現時点でポリシーマニフェストを処理できません。ポリシーファイルの管理には、Bradleyが開発したnode-policy CLIヘルパーを使えます。
node-policyのintegrity:addコマンドを実行すると、現在のディレクトリにあるすべてのファイルの暗号学的ハッシュを含むポリシーマニフェストを作成できます。.git/ディレクトリからnode_modules/の全コンテンツまで、すべてが対象となるため、生成には少し時間がかかります。
この仕組みを説明するために、typeformのアンケート結果をエクスポートするために作成したCLI用Node.jsモジュールで試してみます。
node-policyを実行し、現在のディレクトリ内にあるすべてのファイル(最後のドットで指定)を対象とする整合性マニフェストを作成します。また、暗号学的ハッシュ関数に使うアルゴリズムを指定します。選択できるのはsha256、sha384、sha512で、いずれもSubresource IntegrityのHTML仕様に対応しています。

生成されたプロジェクトのポリシーファイルは、ユーザーのホームディレクトリに保存されます。.node-policy.jsonの一部を以下に示します。ファイルのURLと整合性ハッシュを含むマニフェストの構造を確認できます。
別のプロジェクトディレクトリでnode-policy CLIを実行すると、このポリシーマニフェストにファイルが追加されます。これはnode-policy独自の実装であり、仕様やガイドラインではありません。
node-policyがポリシーファイルをユーザーのホームディレクトリに作成するのはなぜでしょうか。整合性ポリシーに関する包括的なベストプラクティスはまだ標準化されていませんが、このファイルは信頼できるリソースの基準となるため、何らかの方法で改ざんされないよう保護するのが最善です。ファイルを読み取り専用に設定し、アクセスされる可能性のあるディレクトリの外に配置することをおすすめします。
ファイルの改ざんとNode.jsによる検出の仕組みを再現するため、CLIプロジェクトに含まれるbin/cli.jsのコードを少し変更しました。実行可能なCLIのJavaScriptコードをNode.jsで実行すると、CommonJSモジュールを読み込む前にハッシュが異なることを検出し、エラーを出してNode.jsをコマンドプロンプトに戻します。

現在の実装では、エラーをスローしたりプログラムを終了したりする代わりに、整合性の不一致をログに記録できます。これは、ポリシーマニフェストファイルのトップレベルオブジェクトにonerrorプロパティを追加することで実現できます。
まとめ
Node.jsへのセキュリティ機能の組み込みは着実に進んでおり、近い将来さらに多くの機能が登場するでしょう。整合性ポリシー機能はまだ実験段階であり、Node.js 11.8.0以降でのみ利用できる点にご注意ください。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。



