技術探し

JavaScriptを中心に記事を書いていきます :;(∩´﹏`∩);:

Node.jsをPolicyにより安全に実行する

この記事は、Node.js Advent Calendar 2019の18日目です。

Policy とは?

nodejs.org

実行コードを制御するセキュリティ機構がNode.jsに入りました。
ポリシーファイルを使い、整合性のチェックを行います。
これにより、requireしたときにファイルが変化していないことを保証することが可能です。

docs.google.com

アルゴリズムは、w3cにあるSRIと同様です。

www.w3.org

github.com

この機能は、まだ実験中のフェーズなためフラグが必要となります。

使い方

// app.js

console.log('app');

require('fs');
require('./foo.js');
// foo.js

console.log('foo');

最初に各ファイルのハッシュ値を生成する必要があります。

$ printf "sha384-$(cat app.js | openssl dgst -sha384 -binary | base64)"
sha384-stoY+K7ZeOkSLHmCYOOrfWcLsKFb1Niv/dkz6f9Q0UP5FQi9pRTglvtGcQ/IPyZR

$ printf "sha384-$(cat foo.js | openssl dgst -sha384 -binary | base64)"
sha384-1RHAoU62Cn5DMHZLSZZKEnvcml+GOtj5O4BXAUohiYtjGzo0v/iFIM7KOxRwoG7P

policy.jsonを作成し、以下のように登録します。
これは、実行ファイルすべて列挙する必要があります。(entry-point含め)

{
  "resources": {
    "./app.js": {
      "integrity": "sha384-stoY+K7ZeOkSLHmCYOOrfWcLsKFb1Niv/dkz6f9Q0UP5FQi9pRTglvtGcQ/IPyZR",
      "dependencies": {
        "fs": true,
        "./foo.js": "./foo.js"
      }
    },
    "./foo.js": {
      "integrity": "sha384-1RHAoU62Cn5DMHZLSZZKEnvcml+GOtj5O4BXAUohiYtjGzo0v/iFIM7KOxRwoG7P"
    }
  }
}

dependencies は booleanでも可能ですが、本番環境では推奨されません。
今回は、ビルトインモジュールのfsなのでtrueとしています。
各ファイルでrequireするモジュールファイルは、すべて列挙する必要性があります。

Dependency Redirection(dependencies)は、require.cachemodule.constructor等のアクセスに対しては、防ぐことができません。
つまり、requireのみのチェックを行うということになります。

以下のようにpolicy.jsonを指定して実行します。

$ node --experimental-policy=policy.json app.js

まとめ

厳格に行うのであれば、コードよりハッシュ値は変わるためPolicyを使うのは有効です。
しかしこれを一つづつ行うのは大変なため、何かしらのCLIで一括で行える機構が必要です。
まだユーザーランドには自分が知る限り存在しないため今後に期待です。