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

2019 / 12 / 18

Edit
🚨 This article hasn't been updated in over a year
💁‍♀️ This post was copied from Hatena Blog

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

Policy とは?


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

A Node.js Security Model A Node.js Security Model Intent This document proposes a way to introduce a set of features to Node....

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

https://www.w3.org/TR/SRI/#the-integrity-attribute

https://github.com/nodejs/node/blob/master/lib/internal/policy/sri.js

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

使い方

// 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 で一括で行える機構が必要です。 まだユーザーランドには自分が知る限り存在しないため今後に期待です。