ホームページ > ウェブフロントエンド > jsチュートリアル > Node.js アプリケーションの保護: 包括的なガイド

Node.js アプリケーションの保護: 包括的なガイド

Patricia Arquette
リリース: 2024-12-08 14:27:10
オリジナル
373 人が閲覧しました

Securing Your Node.js Application: A Comprehensive Guide

今日のデジタル環境では、Node.js アプリケーションのセキュリティを確保することが最も重要です。 Netflix や Uber のような世界的リーダーから、次の大きなものを構築するスタートアップまで、Node.js は最も要求の厳しい高性能アプリケーションの一部を支えています。ただし、アプリケーションの脆弱性は、不正アクセス、データ侵害、ユーザーの信頼の喪失につながる可能性があります。

このガイドは、実践的なセキュリティの実践と OWASP Web セキュリティ テスト ガイド (WSTG) の重要な概念を組み合わせて、Node.js アプリケーションの強化に役立ちます。リアルタイム操作を管理している場合でも、数百万のユーザーに拡張している場合でも、この包括的なリソースにより、アプリケーションの安全性、信頼性、回復力が確保されます。


情報収集(WSTG-INFO)

情報収集 は、多くの場合、攻撃者がアプリケーションについて詳しく知るために行う最初のステップです。収集できる情報が増えるほど、脆弱性を特定して悪用することが容易になります。

一般的な Express.js サーバー構成とフィンガープリント

デフォルトでは、Express.js にはサーバーに関する情報が誤って公開される可能性のある設定が含まれています。一般的な例は、アプリケーションが Express を使用していることを示す X-Powered-By HTTP ヘッダーです。

脆弱なコードの例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

この設定では、すべての HTTP 応答に X-Powered-By: Express ヘッダーが含まれます。

問題:

  • フィンガープリンティング: 攻撃者はこのヘッダーを使用して、使用しているテクノロジーを特定できます。 Express を実行していることがわかれば、特定のバージョンの Express または Node.js の既知の脆弱性に合わせて攻撃を調整することができます。

軽減策:

攻撃者がサーバーのフィンガープリントを取得するのを困難にするには、このヘッダーを無効にします。

改善されたコード:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ヘルメットによる軽減策の強化:

より良いアプローチは、アプリのセキュリティを向上させるためにさまざまな HTTP ヘッダーを設定するヘルメット ミドルウェアを使用することです。

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

なぜヘルメットを使用するのですか?

  • 包括的なセキュリティ ヘッダー: ヘルメットは、既知の Web 脆弱性からアプリを保護するのに役立つ複数の HTTP ヘッダーを設定します。
  • 使いやすさ: たった 1 行で、アプリケーションのセキュリティ体制が大幅に強化されます。

構成および展開管理テスト (WSTG-CONF)

構成と展開の管理は、アプリケーションのセキュリティの重要な側面です。設定ミスは、攻撃者にとって無防備なドアとなる可能性があります。

本番環境で開発モードで実行

運用サーバー上で開発モードでアプリケーションを実行すると、詳細なエラー メッセージやスタック トレースが公開される可能性があります。

脆弱なコードの例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

このセットアップでは、詳細なエラー メッセージがクライアントに送信されます。

問題:

  • 情報漏洩: 詳細なエラー メッセージとスタック トレースにより、アプリケーションの構造、依存関係、ファイル パスに関する機密情報が明らかになる可能性があります。
  • 悪用の促進: 攻撃者はこの情報を使用して潜在的な脆弱性を特定し、標的型攻撃を作成できます。

軽減策:

NODE_ENV を「実稼働」に設定し、実稼働環境で一般的なエラー メッセージを使用します。

改善されたコード:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ベストプラクティス:

  • 環境変数を正しく設定します: 本番環境で NODE_ENV が「production」に設定されていることを確認してください。
  • 内部ログ: エンドユーザーに詳細を公開することなく、デバッグ目的でエラーを内部的に記録します。

デフォルトまたは弱い認証情報の使用

JSON Web トークン (JWT) に署名するための単純な秘密キーなど、デフォルトの資格情報や弱い資格情報を使用することは、よくあるセキュリティ上の間違いです。

脆弱なコードの例:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 弱い秘密キー: 「secret」のような単純または一般的な文字列を使用すると、攻撃者がキーを推測したりブルートフォース攻撃したりすることが容易になります。
  • ハードコードされたシークレット: コードにシークレットを直接保存すると、コードベースが侵害された場合に漏洩のリスクが高まります。
  • トークン偽造: 秘密キーを知っている攻撃者は、有効な JWT を偽造し、不正アクセスを取得する可能性があります。

軽減策:

強力で安全な秘密キーを使用し、安全に保管してください。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

ベストプラクティス:

  • 環境変数: シークレットをバージョン管理にコミットしないでください。ソース管理にチェックインされていない環境変数または構成ファイルを使用します。
  • シークレットのローテーション: シークレットを定期的にローテーションするプロセスを実装します。
  • 構成の検証: アプリケーションの起動時に、必要な環境変数がすべて設定されていることを確認します。

アイデンティティ管理テスト (WSTG-IDNT)

ID 管理は、ユーザー アカウントを保護し、不正アクセスを防止するために重要です。

弱いユーザー名ポリシーとアカウントの列挙

脆弱なユーザー名を許可し、特定のエラー メッセージを提供すると、アカウント列挙攻撃につながる可能性があります。

脆弱なコードの例:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 弱いユーザー名: 短いまたは単純なユーザー名を許可すると、アカウントが侵害されるリスクが増加します。
  • アカウントの列挙: 特定のエラー メッセージは、攻撃者が有効なユーザー名を判断するのに役立ちます。

軽減策:

ユーザー名の検証を実装し、一般的なエラー メッセージを使用します。

改善されたコード:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • ユーザー名検証: ユーザー名が特定の基準を満たしていることを確認し、脆弱なエントリを減らします。
  • 一般的なエラー メッセージ: 攻撃者がエラー応答を通じて有効なユーザー名を特定できないようにします。

認証テスト (WSTG-ATHN)

認証メカニズムは、ユーザー ID を検証し、不正アクセスを防止するために不可欠です。

パスワードおよび 2FA に対するブルートフォース攻撃

保護が欠如しているため、攻撃者は繰り返し試行することでパスワードや 2FA コードを推測できます。

脆弱なコードの例:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 無制限のログイン試行: 攻撃者は、異なるパスワードや 2FA コードを繰り返し試行できます。
  • 弱い 2FA 実装: 静的または予測可能な 2FA コードは脆弱です。

軽減策:

レート制限を実装し、2FA セキュリティを強化します。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

追加措置:

  • 失敗した試行後に CAPTCHA を使用する: ログイン試行が数回失敗した後、人間のユーザーを確認するために CAPTCHA を導入します。
  • 2FA に TOTP を採用する: 動的で安全な 2FA コードには時間ベースのワンタイム パスワードを使用します。

説明:

  • レート制限: ログイン試行を制限することで、自動化された攻撃のリスクを軽減します。
  • 強化された 2FA: 時間ベースのコードは、静的コードよりもセキュリティを向上させます。

認可テスト (WSTG-ATHZ)

認可 により、ユーザーは使用を許可されたリソースのみにアクセスできるようになり、不正なアクションが防止されます。

安全でない直接オブジェクト参照 (IDOR)

ユーザーはリクエスト内の識別子を操作することで、未承認のリソースにアクセスできます。

脆弱なコードの例:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 不正アクセス: ユーザーは orderId パラメータを変更することで、アクセスすべきではないデータにアクセスできます。

軽減策:

アクセスを提供する前にリソースの所有権を検証します。

改善されたコード:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 所有権の検証: 要求されたリソースが認証されたユーザーに属していることを確認します。
  • アクセス制御: ユーザーがリクエスト パラメーターを操作して他人のデータにアクセスできないようにします。

セッション管理テスト (WSTG-SESS)

セッション管理は、ユーザーの状態を維持し、安全な対話を確保するために重要です。

有効期限のないトークン

有効期限のないトークンは、侵害された場合にセキュリティ上のリスクを引き起こします。

脆弱なコードの例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 永続トークン: 有効期限のないトークンは無期限に有効なため、悪用される可能性が高まります。

軽減策:

トークンの有効期限を設定します。

改善されたコード:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • トークンの有効期限: 有効期間を制限し、トークンが侵害された場合のリスクを軽減します。
  • セキュリティのベスト プラクティス: トークンを定期的に更新すると、全体的なセキュリティが強化されます。

安全でないトークンストレージ

トークンを localStorage に保存すると、クロスサイト スクリプティング (XSS) 攻撃にさらされます。

脆弱なコードの例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • クライアント側の露出: 悪意のあるスクリプトが localStorage にアクセスし、トークンを盗んだり、セッションをハイジャックしたりする可能性があります。

軽減策:

HTTP のみの Cookie を使用してトークンを安全に保存します。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • HTTP のみの Cookie: JavaScript にアクセスできないため、XSS リスクが軽減されます。
  • Secure and SameSite Flags: 中間者攻撃およびクロスサイト リクエスト フォージェリ攻撃に対する保護を強化します。

入力検証テスト (WSTG-INPV)

入力検証 は、ユーザーが提供したデータが安全かつ期待どおりであることを保証し、インジェクション攻撃を防ぎます。

入力検証の欠如

検証せずにユーザー入力を受け入れて処理すると、脆弱性が発生する可能性があります。

脆弱なコードの例:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

ログイン後にコピー
ログイン後にコピー

問題:

  • インジェクション攻撃: 未検証の入力は、SQL インジェクション、NoSQL インジェクション、またはその他のコード インジェクション攻撃につながる可能性があります。

軽減策:

すべてのユーザー入力を検証し、サニタイズします。

改善されたコード:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 入力検証: 入力が期待される基準を満たしているかどうかをチェックします。
  • 入力のサニタイズ: 有害な可能性のある文字を削除またはエスケープします。
  • 安全なデータベース クエリ: パラメーター化されたクエリを使用すると、インジェクション攻撃を防止します。

エラー処理のテスト (WSTG-ERRH)

適切なエラー処理により、機密情報の漏洩が回避され、ユーザー エクスペリエンスが向上します。

機密エラー情報の公開

詳細なエラー メッセージにより、攻撃者にシステム内部の情報が明らかになる可能性があります。

脆弱なコードの例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 情報漏洩: 攻撃者はアプリケーションの構造と潜在的な脆弱性についての洞察を得ることができます。

軽減策:

一般的なエラー メッセージを使用し、詳細なエラーを内部的に記録します。

改善されたコード:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 内部ログ: 詳細なエラー情報を安全に保管します。
  • ユーザーフレンドリーなメッセージ: 機密情報を明らかにすることなく、一般的なメッセージを提供します。

弱い暗号のテスト (WSTG-CRYP)

暗号化は機密データを保護します。弱い暗号化手法を使用すると、セキュリティが損なわれます。

安全でないハッシュアルゴリズムの使用

古いアルゴリズムでパスワードをハッシュするのは安全ではありません。

脆弱なコードの例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 弱いハッシュ: MD5 や SHA-1 などのアルゴリズムは衝突攻撃に対して脆弱であるため、パスワード ハッシュには使用しないでください。

軽減策:

パスワード用に設計された強力なハッシュ アルゴリズムを使用します。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • Bcrypt: ソルティングと複数回のハッシュを組み込んだ堅牢なハッシュ関数。
  • パスワード セキュリティ: 攻撃者がパスワードをリバース エンジニアリングすることを計算上不可能にします。

秘密キーのハードコーディング

シークレットをコードに直接保存すると、漏洩のリスクが高まります。

脆弱なコードの例:

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();

// Weak secret key
const SECRET_KEY = 'secret';

app.post('/login', (req, res) => {
  // Authenticate user (authentication logic not shown)
  const userId = req.body.userId;

  // Sign the JWT with a weak secret
  const token = jwt.sign({ userId }, SECRET_KEY);
  res.json({ token });
});

app.get('/protected', (req, res) => {
  const token = req.headers['authorization'];

  try {
    // Verify the token using the weak secret
    const decoded = jwt.verify(token, SECRET_KEY);
    res.send('Access granted to protected data');
  } catch (err) {
    res.status(401).send('Unauthorized');
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

ログイン後にコピー
ログイン後にコピー

問題:

  • 秘密の暴露: コードベースが侵害されると、ハードコードされた秘密が簡単に抽出される可能性があります。

軽減策:

シークレットを環境変数または安全な構成ファイルに保存します。

改善されたコード:

const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 環境変数: コードベースとバージョン管理システムに機密情報が入らないようにします。
  • セキュリティ対策: 偶発的な暴露のリスクを軽減します。

ビジネス ロジック テスト (WSTG-BUSL)

ビジネス ロジックの脆弱性は、アプリケーション フローが意図しない方法で操作される可能性がある場合に発生します。

一括操作の悪用

無制限のデータ操作は、パフォーマンスの問題やデータ漏洩につながる可能性があります。

脆弱なコードの例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • サービス拒否 (DoS): 大量のデータのエクスポートにより、サーバーのリソースが枯渇する可能性があります。
  • データ漏洩: 無制限のアクセスにより機密情報が漏洩する可能性があります。

軽減策:

ページネーションとアクセス制御を実装します。

改善されたコード:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • ページネーション: 返されるデータの量を制御し、リソースの枯渇を防ぎます。
  • アクセス制御: ユーザーが自分のデータのみにアクセスできるようにします。

クライアント側テスト (WSTG-CLNT)

クロスサイト スクリプティング (XSS) などの攻撃からユーザーを守るには、クライアント側の脆弱性から保護することが不可欠です。

xss ライブラリを使用したユーザー入力のエスケープ

クライアント側スクリプトでのユーザー入力の不適切な処理は、XSS 攻撃につながる可能性があります。

脆弱なコードの例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • 安全でない DOM 操作: サニタイズされていないユーザー入力を innerHTML に挿入すると、悪意のあるスクリプトの実行が可能になります。

軽減策:

xss ライブラリを使用して、レンダリング前にユーザー入力をサニタイズします。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 入力のサニタイズ: xss ライブラリは、潜在的に危険なコンテンツをエスケープまたは削除することで入力をクリーンアップします。
  • スクリプトの実行の防止: 悪意のあるスクリプトを無効化し、ブラウザでの実行を防ぎます。

ベストプラクティス:

  • 可能な場合は textContent を使用します: ユーザー入力を textContent に割り当てると、それがプレーン テキストとして扱われます。
const express = require('express');
const app = express();

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
  • クライアント側とサーバー側の検証を組み合わせる: 多層防御のアプローチによりセキュリティが強化されます。

API テスト (WSTG-APIT)

データ漏洩や不正アクセスを防ぐには、API エンドポイントを保護することが重要です。

GraphQL イントロスペクションの公開

本番環境で GraphQL イントロスペクションを有効にしたままにすると、API スキーマが明らかになります。

脆弱なコードの例:

const express = require('express');
const app = express();

// Disable the X-Powered-By header
app.disable('x-powered-by');

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • スキーマの開示: 攻撃者は API スキーマを探索し、標的型攻撃の作成を支援する可能性があります。

軽減策:

実稼働環境ではイントロスペクションを無効にします。

改善されたコード:

const express = require('express');
const helmet = require('helmet');
const app = express();

// Use Helmet to secure headers
app.use(helmet());

// Your routes here

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 条件付きイントロスペクション: 開発中はイントロスペクションを許可しますが、運用環境では無効にします。
  • セキュリティ強化: スキーマの詳細を非表示にすることで攻撃対象領域を削減します。

無制限のクエリの複雑さ

深くネストされたクエリや複雑なクエリは、サーバー リソースを使い果たす可能性があります。

脆弱なコードの例:

// app.js
const express = require('express');
const app = express();

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send(err.stack); // Sends stack trace to the client
});

// Your routes here

app.listen(3000);

ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

問題:

  • サービス拒否 (DoS): 複雑なクエリは CPU とメモリの使用率を高める可能性があります。

軽減策:

クエリの深さと複雑さを制限します。

改善されたコード:

// app.js
const express = require('express');
const app = express();

// Your routes here

// Error handling middleware
if (app.get('env') === 'production') {
  // Production error handler
  app.use((err, req, res, next) => {
    // Log the error internally
    console.error(err);
    res.status(500).send('An unexpected error occurred.');
  });
} else {
  // Development error handler (with stack trace)
  app.use((err, req, res, next) => {
    res.status(500).send(`<pre class="brush:php;toolbar:false">${err.stack}
`); }); } app.listen(3000);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

説明:

  • 深さの制限: リソースの枯渇を防ぐためにクエリの深さを制限します。
  • パフォーマンス保護: API の応答性と利用性を確保します。

結論

Node.js アプリケーションの保護には、多層のアプローチが必要です。

  • 情報漏洩の防止: コードとサーバー構成をクリーンアップして、機密データの公開を防ぎます。
  • 構成を安全に管理: デフォルトの認証情報を削除し、構成ファイルを保護します。
  • 入力の検証とサニタイズ: ユーザー入力を決して信頼しないでください。
  • 適切な認証と認可を実装する: ユーザーが適切なアクセス権を持っていることを確認します。
  • 強力な暗号化を使用する: 安全なアルゴリズムとキー管理でデータを保護します。
  • エラーを適切に処理します: 機密情報の公開は避けてください。
  • クライアント側の対話の保護: XSS およびその他のブラウザベースの攻撃を軽減します。
  • 安全な API: データの公開を制御し、レート制限を適用します。

これらのプラクティスを統合することで、アプリケーションのセキュリティを強化し、ユーザー データを保護し、信頼を維持できます。


さらに読む

  • OWASP Web セキュリティ テスト ガイド (WSTG): OWASP WSTG
  • Node.js セキュリティ ガイド: Node.js セキュリティ
  • Express.js セキュリティのヒント: Express セキュリティのベスト プラクティス
  • GraphQL セキュリティのベスト プラクティス: Apollo GraphQL セキュリティ
  • OWASP トップ 10: OWASP トップ 10
  • MDN Web ドキュメント - Web セキュリティ: MDN Web セキュリティ

注: このガイドでは、一般的な推奨事項を提供します。特定のセキュリティ上の懸念については、専門家にご相談ください。

以上がNode.js アプリケーションの保護: 包括的なガイドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート