Skip to main content

一般的な 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など)を管理することを避け、歴戦のユーザー管理システムの恩恵を受けるために、一元化されたユーザー管理システムの利用を検討する

�✔ OWASP A5: 壊れたアクセスコントロール

  • 最小権限の原則を尊重する - すべてのコンポーネントと DevOps 担当者は、必要最低限の情報とリソースにのみアクセスできるようにする
  • アカウント管理以外では、ルート(フル権限)アカウントでの作業は 絶対に 行わない
  • ロール/サービスアカウントに代わって、すべてのインスタンス/コンテナを実行する
  • ユーザーではなくグループに権限を割り当てる。これにより、ほとんどの場合、権限管理がより簡単で透明性の高いものになるはずである

✔ OWASP A6: セキュリティの設定ミス

  • 本番環境内部へのアクセスは内部ネットワークを介してのみ行い、SSH または他の手段を利用する。 絶対に 内部サービスは外部に公開しない
  • 内部ネットワークアクセスを制限する - どのリソースが他のリソースにアクセスできるかを明示的に設定する(例えば、ネットワークポリシーやサブネットなど)
  • Cookie(cookies)を利用している場合は、クライアントサイドの JavaScript がCookieにアクセスすることを防ぐために「HttpOnly」の設定を優先的に行う
  • Cookieを利用している場合は、「same site」を設定し、同ドメインからのリクエストのみ指定されたCookieを取得できるようにする
  • 各 VPC を厳格で性異言されたアクセスルールで保護する
  • STRIDE や DREAD のような標準的なセキュリティ脅威モデルを利用して脅威に優先順位を付ける
  • HTTP(S) と TCP ロードバランサーを使用して DDoS 攻撃に対して保護をする
  • 専門機関による定期的なペネトレーションテストを実施する

✔ OWASP A3: センシティブなデータの露出

  • SSL/TLS 接続のみを受け付け、ヘッダーを利用して String-Transport-Security を強制する
  • ネットワークをセグメント(サブネットなど)に分割し、各ノードが必要最低限のネットワークアクセス権限を持っていることを確認する
  • インターネットアクセスを必要としない全てのサービス/インスタンスをグループ化し、外向きの接続を明示的に禁止する(プライベートサブネット)
  • AWS KMS、HachiCorp Vault または Google Cloud KMS のような vault 製品にシークレットを保存する
  • メタデータを使用して、機密性の高いインスタンスメタデータを隔離する
  • データが物理的な境界線を超える際は、運んでいるデータを暗号化する
  • シークレットをログ情報の中に含まない
  • フロントエンドでは平文のパスワードを表示しないようにし、バックエンドでは必要な対策を講じて決して機密情報を平文で保存しないようにする

✔ OWASP A9: 既知のセキュリティ脆弱性を持つコンポーネントの使用

  • docker イメージをスキャンして既知の脆弱性を探す(Docker や他のベンダーのスキャンサービスを利用する)
  • インスタンス(マシン)の自動パッチ適用とアップグレードを有効にして、セキュリティパッチが不足している古いバージョンの OS を実行しないようにする
  • ユーザに「id」「access」「refresh」といったトークンを提供することで、アクセストークンの期限を短くして、refresh トークンで更新されるようにする
  • AWS CloudTrail のようなサービスを利用して、クラウドや管理サービスに対する API コール(例えば、誰がS3バケットを削除したのか?)のログを残し、監査を行う
  • クラウドプロバイダー(AWS Trusted Advisor など)のセキュリティチェッカーを実行する

✔ OWASP A10: ロギングとモニタリングの不足

  • ユーザーログイン、新規ユーザー作成、権限変更といった操作において、目立った、または疑わしい監査対象イベントが発生したらアラートする
  • 異常な回数のログインの失敗(もしくはパスワードを忘れた、などの同様のアクション)が発生した場合にはアラートする
  • 各 DB レコードにおいて更新を行った時刻とユーザー名を含める

✔ OWASP A7: クロスサイトスクリプティング(XSS)

  • EJS、Pug、React、Angular など、設計によって自動的に XSS 回避するテンプレートエンジンやフレームワークを使用する。XSS 対策のそれぞれのメカニズムの限界を知り、対象外のユースケースに適切に対処する
  • HTML 出力のコンテキスト(body、属性、JavaScript、CSS、URL など)に基づいて、信頼できない HTTP リクエストデータをエスケープすることで、反射型および格納型の XSS 脆弱性を解決する
  • クライアントサイドでブラウザの document を変更する際に context-sensitive エンコーディングを適用して DOM XSS 対策する
  • XSS を緩和する多層防御(defense-in-depth)として Content-Security Policy (CSP) を有効化する

✔ 個人識別可能な情報(PIIデータ)の保護

  • 個人情報(PII)とは、特定の個人を識別できるデータのことである
  • アプリケーションでは個人情報は暗号化して保護する
  • その地域におけるデータプライバシーに関する法律に従う

参考となる法律:

✔ security.txt ファイルを配置する[プロダクション]

TL;DR: 本番環境において、 Web サイトや Web アプリケーションの /.well-known ディレクトリ(/.well-known/security.txt)またはルートディレクトリ(/security.txt)配下に security.txt というテキストファイルを置いてください。security.txt ファイルは、セキュリティリサーチャーが脆弱性を報告するための詳細と、報告の送り先となる責任者および組織の連絡先の詳細(E メール、電話番号)を含む必要があります。

さもないと: 脆弱性についての報告を受けられない可能性があります。脆弱性への対応をすぐに行う機会を逃すことになります。

🔗 さらに読む: security.txt


✔ SECURITY.md ファイルを配置する[オープンソース]

TL;DR: プロジェクトのセキュリティ脆弱性を責任を持って報告するための方法を示すために、 SECURITY.md ファイルを、リポジトリのルートディレクトリ、docs ディレクトリ、もしくは .github ディレクトリの中に置いてください。SECURITY.md ファイルは、セキュリティリサーチャーが脆弱性を報告するための詳細と、報告の送り先となる責任者および組織の連絡先の詳細(E メール、電話番号)を含む必要があります。

さもないと: 脆弱性についての報告を受けられない可能性があります。脆弱性への対応をすぐに行う機会を逃すことになります。

🔗 さらに読む: SECURITY.md