一般的な Node.js セキュリティベストプラクティス
この一般的なセキュリティガイドラインのセクションには、多くのフレームワークや慣習において標準となっているベストプラクティスが含まれています。例えば、SSL/TLS を使用してアプリケーションを実行するということは、優れたセキュリティ上の利点を享受するためにあらゆる環境において従われる、よくあるガイドラインや慣習です。
クライアント/サーバー間の通信を暗号化するために SSL/TLS を使用する
TL;DR: 無料の SSL/TLS 証明書 が提供されそれらが簡単に設定できる時代には、セキュアなサーバーを使用することの利点と欠点を比較する必要はもはやありません。なぜなら、セキュリティやモダンなテクノロジーのサポート、そして信頼性といった利点は、明らかにHTTPと比べてオーバーヘッドが大きいといったような欠点を上回るためです。
さもないと: 接続が暗号化されていない場合には、攻撃者は中間者攻撃を行い、ユーザーの行動を監視し、さらに悪質なアクションを行ってくる可能性があります。
🔗 さらに読む: セキュアな Node.js サーバーを実行する
シークレット値とハッシュ値をセキュアに比較する
TL;DR: シークレット値や HMAC ダイジェストのようなハッシュを比較する場合は、Node.js v6.6.0 以降に Node が提供している crypto.timingSafeEqual(a, b)
関数を使用するべきです。このメソッドは 2 つの与えられたオブジェクトを比較し、データが一致しない場合でも比較を続けます。デフォルトの等値比較メソッドは、文字の不一致だった場合には単純にリターンするだけなので、操作の長さに基づいたタイミング攻撃を可能にします。
さもないと: デフォルトの等値比較演算子を使用すると、2 つのオブジェクトを比較するのにかかった時間に基づいて、重要な情報を漏出してしまうかもしれません。
Node.js を用いてランダムな文字列を生成する
TL;DR: トークンやその他のセキュリティ上重要なユースケースを対象として、擬似ランダム文字列を生成する独自のカスタムビルド関数を使用すると、実際には思ったほどランダムではなく、アプリケーションが暗号攻撃に対して脆弱になる可能性があります。安全なランダム文字列を生成する必要がある場合は、システムが提供するエントロピーを用いた crypto.RandomBytes(size, [callback])
関数を使用してください。
さもないと: 暗号学的に安全な方法を使わずに擬似ランダム文字列を生成すると、攻撃者が生成結果を予測して再現し、アプリケーションを安全ではないものにしてしまう可能性があります。
続けて以下に、OWASP プロジェクトから重要なアドバイスをいくつか挙げてみました。
OWASP A2: 壊れた認証
- 重要なサービスやアカウントは MFA/2FA を要求する
- SSH キーも含め、パスワードやアクセスキーは頻繁に変更する
- 運用とアプリケーション内両方のユーザー管理おいて、強力なパスワードポリシーを適用する(🔗 OWASP パスワードの推奨事項)
- デフォルトのクレデンシャル情報を使用してアプリケーションを出荷またはデプロイしない(特に管理者ユーザーや外部サービスに依存している場合)
- OAuth や OpenID のような標準的な認証方法のみを使用する - ベーシック認証の使用は 避ける
- 認証レートリミット: 期間 Y における X 回を超えるログインを拒否する
- ログインに失敗した場合は、ユーザ名とパスワードのどちらの確認に失敗したかをユーザに知らせることなく、一般的な認証エラーを返す
- 従業員ごとに複数のアカウント(例えば、GitHub、AWS、Jenkinsなど)を管理することを避け、歴戦のユーザー管理システムの恩恵を受けるために、一元化されたユーザー管理システムの利用を検討する