StrongLoop / IBMによって提供されるこの翻訳.

本書は、英語の資料と比較すると古くなっている可能性があります。最新の更新については、英語版の資料を参照してください。

実稼働環境におけるベスト・プラクティス: セキュリティー

概説

実稼働」という用語は、ソフトウェアのライフサイクルにおいて、アプリケーションや API をエンド・ユーザーまたはコンシューマーが広く使用できる段階を指します。対照的に、「開発」段階では、まだコードの作成とテストを積極的に行っていて、アプリケーションへの外部アクセスは不可能です。対応するシステム環境は、それぞれ実稼働 環境と開発 環境と呼ばれています。

開発環境と実稼働環境は通常、別々にセットアップされ、それぞれの要件は大きく異なっています。開発環境では許可されることが、実稼働環境では許可されないことがあります。例えば、開発環境ではデバッグのためにエラーの詳細なロギングを実行できますが、同じ動作が実稼働環境ではセキュリティー上の問題となります。開発環境では、スケーラビリティー、信頼性、パフォーマンスについて心配する必要はありませんが、それらは実稼働環境では重大な問題となります。

この記事では、実稼働環境にデプロイされた Express アプリケーションのセキュリティーに関するベスト・プラクティスについて説明します。

非推奨バージョンや脆弱なバージョンの Express を使用しない

Express 2.x および 3.x は保守されなくなりました。これらのバージョンにおけるセキュリティーとパフォーマンスの問題は修正されません。これらのバージョンを決して使用しないでください。まだバージョン 4 に移行していない場合は、マイグレーション・ガイドに従ってください。

また、セキュリティー更新ページにリストされている脆弱な Express バージョンを使用していないことを確認してください。使用している場合は、安定しているリリース (最新を推奨します) に更新してください。

TLS を使用する

アプリケーションが機密データを処理または送信する場合は、Transport Layer Security (TLS) を使用して、接続とデータを保護してください。このテクノロジーは、データをクライアントからサーバーへの送信前に暗号化するため、一般的 (容易) なハッキングを防止します。Ajax と POST 要求は明白ではなく、ブラウザーに対して「非表示」になっているように見えますが、そのネットワーク・トラフィックは、パケットのスニッフィング中間者攻撃に対して脆弱です。

Secure Socket Layer (SSL) 暗号化については理解されていると思います。TLS は、単に SSL が進化したものです。つまり、以前に SSL を使用していた場合は、TLS へのアップグレードを検討してください。一般に、TLS を処理するために Nginx を使用することをお勧めします。Nginx (およびその他のサーバー) で TLS を構成するための解説については、Recommended Server Configurations (Mozilla Wiki) を参照してください。

また、Let’s Encrypt は、無料の TLS 証明書を取得するための便利なツールです。このツールは、Internet Security Research Group (ISRG) が提供する、無料の自動的かつオープンな認証局 (CA) です。

Helmet を使用する

Helmet は、HTTP ヘッダーを適切に設定することによって、いくつかの既知の Web の脆弱性からアプリケーションを保護します。

Helmet は、実際には、セキュリティー関連の HTTP ヘッダーを設定する 9 個の小さなミドルウェア関数の単なる集合です。

その他のモジュールと同様に Helmet をインストールします。


$ npm install --save helmet

次に、コードで使用します。


...
var helmet = require('helmet');
app.use(helmet());
...

少なくとも X-Powered-By ヘッダーを無効にする

Helmet を使用しない場合は、少なくとも X-Powered-By ヘッダーを無効にしてください。アタッカーが、(デフォルトで有効になっている) このヘッダーを使用して、Express を実行しているアプリケーションを検出し、具体的に対象を絞った攻撃を開始する可能性があります。

そのため、app.disable() メソッドを使用してこのヘッダーをオフにすることがベスト・プラクティスです。


app.disable('x-powered-by');

helmet.js を使用する場合は、この操作が自動的に実行されます。

Cookie を介してアプリケーションが悪用されないように、デフォルトの セッション Cookie 名を使用しないでください。また、Cookie のセキュリティー・オプションを適切に設定してください。

主なミドルウェア Cookie セッション・モジュールが 2 つあります。

これらの 2 つのモジュールの主な違いは、Cookie セッション・データの保存方法です。express-session ミドルウェアは、セッション・データをサーバーに保管します。セッション・データではなく、Cookie 自体の中にあるセッション ID のみを保存します。デフォルトで、メモリー内のストレージを使用し、実稼働環境向けには設計されていません。実稼働環境では、スケーラブルなセッション・ストアをセットアップする必要があります。互換性のあるセッション・ストアのリストを参照してください。

対照的に、cookie-session ミドルウェアは、Cookie が支持するストレージを実装します。セッション・キーだけでなく、セッション全体を Cookie に対して直列化します。これは、セッション・データが比較的小規模で、(オブジェクトではなく) プリミティブ値として容易にエンコードできる場合にのみ使用してください。ブラウザーは Cookie 当たり最小 4096 バイトをサポートすることが想定されますが、その制限を必ず超えないようにするために、ドメイン当たり 4093 バイトのサイズを超えないようにしてください。また、Cookie データがクライアントに対して可視になることに注意してください。何らかの理由でデータを保護したり覆い隠したりする必要がある場合は、express-session を使用することをお勧めします。

デフォルトのセッション Cookie 名を使用すると、アプリケーションが攻撃を受けやすくなります。提起されているセキュリティー問題は X-Powered-By と似ています。潜在的なアタッカーがこれを使用して、サーバーに対して指紋認証し、攻撃の標的にする可能性があります。

この問題を回避するには、汎用な Cookie 名を使用します。例えば、express-session ミドルウェアを使用します。


var session = require('express-session');
app.set('trust proxy', 1) // trust first proxy
app.use( session({
   secret : 's3Cur3',
   name : 'sessionId',
  })
);

セキュリティーを強化するために、以下の Cookie オプションを設定します。

次に、cookie-session ミドルウェアの使用例を示します。


var session = require('cookie-session');
var express = require('express');
var app = express();

var expiryDate = new Date( Date.now() + 60 * 60 * 1000 ); // 1 hour
app.use(session({
  name: 'session',
  keys: ['key1', 'key2'],
  cookie: { secure: true,
            httpOnly: true,
            domain: 'example.com',
            path: 'foo/bar',
            expires: expiryDate
          }
  })
);

依存関係がセキュアであることを確認する

npm を使用したアプリケーションの依存関係の管理は、強力で便利な方法です。ただし、使用するパッケージに、アプリケーションにも影響を与える可能性がある重大なセキュリティーの脆弱性が含まれている可能性があります。アプリケーションのセキュリティーの強さは、依存関係の中で「最も弱いリンク」程度でしかありません。

nsprequireSafe という 2 つのツールの一方または両方を使用して、使用するサード・パーティー・パッケージのセキュリティーを確保します。これらの 2 つのツールが実行する処理は大体同じです。

nsp は、Node Security Project の脆弱性データベースを確認して、アプリケーションが既知の脆弱性を持つパッケージを使用しているかどうかを判別するコマンド・ライン・ツールです。次のようにしてインストールします。


$ npm i nsp -g

このコマンドを使用して、npm-shrinkwrap.json ファイルを検証のために nodesecurity.io に送信します。


$ nsp audit-shrinkwrap

このコマンドを使用して、package.json ファイルを検証のために nodesecurity.io に送信します。


$ nsp audit-package

次に、Node モジュールを監査するための requireSafe の使用例を示します。


$ npm install -g requiresafe
$ cd your-app
$ requiresafe check

その他の考慮事項

次に、優れた Node.js セキュリティー・チェックリストに記載されているその他の推奨事項をリストします。これらの推奨事項の詳細については、ブログの投稿を参照してください。

その他の既知の脆弱性を回避する

アプリケーションで使用する Express やその他のモジュールに影響を与える可能性がある Node Security Project のアドバイザリーに常に注意してください。一般に、Node Security Project は、Node のセキュリティーに関する知識とツールの優れたリソースです。

最後に、Express アプリケーションは、その他の Web アプリケーションと同様、さまざまな Web ベースの攻撃に対して脆弱になりえます。既知の Web の脆弱性をよく理解して、それらを回避するための予防措置を取ってください。