技術共有

フロントエンド インタビューの質問 50 (CSRF 攻撃を防ぐことができる一般的なフロントエンド セキュリティ対策は何ですか?)

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

ここに画像の説明を挿入します
クロスサイト リクエスト フォージェリ (CSRF) 攻撃を防ぐために、フロントエンド開発では次の一般的なセキュリティ対策を講じることができます。

1.CSRFトークンを使用する

これは、最も一般的に使用される防御メカニズムの 1 つです。

  • トークンの生成: ユーザーがログインすると、サーバーはランダムで予測不可能な CSRF トークンを生成し、サーバー側に保存します。同時に、それは Set-Cookie ヘッダーを通じてクライアントに送信され、ユーザーの Cookie に保存されます。

  • フォーム埋め込みトークン: 保護が必要な各 HTML フォームに、隠しフィールド (<input type="hidden">)、その値は Cookie から読み取られた CSRF トークンに設定されます。

  • トークンの検証 : フォームが送信されると、バックエンドはフォーム データと Cookie 内のトークンを受信します (同一生成元ポリシーにより、ブラウザーは自動的に Cookie を送信します)。サーバー側は、フォーム内のトークンがサーバー側またはセッションに保存されているトークンと一致しているかどうかを検証します。それらが矛盾している場合、リクエストは拒否されます。

2. HTTPリファラーとオリジンヘッダーを確認する

Referer と Origin が改ざんされているか欠落している可能性があるため、完全に信頼できるわけではありませんが、シナリオによっては補助手段として使用できます。

  • リファラーをチェックする処置: HTTP リクエストヘッダーの Referer フィールドを確認して、リクエストが予想されるドメイン名から開始されていることを確認してください。ただし、この方法には制限があることに注意してください。たとえば、HTTPS から HTTP へのダウングレード リクエストではリファラーが送信されません。

  • オリジンヘッダーのチェック: Referer と同様に、Origin ヘッダーはリクエストのソースに関する情報を提供しますが、XMLHttpRequest または Fetch API を使用する場合にのみ送信されます。

3. SameSite Cookie 属性を使用する

クロスサイト アクセスを必要としない Cookie については、SameSite 属性を設定してセキュリティを強化できます。

  • 同じサイト=緩い: Cookie は同じサイトのリクエストでのみ送信され、CSRF から部分的に保護されます。
  • SameSite=厳密: Cookie は同じサイト内および同じページ ナビゲーション内でのみ送信されるため、より強力な保護が提供されますが、予期されるクロスサブドメイン機能の一部に影響を与える可能性があります。
  • 同じサイト=なし: 最新のブラウザの要件に適応するためにクロスサイトで使用する必要がある Cookie の Secure 属性とともに使用する必要があります。

4. カスタムリクエストヘッダーの検証

カスタム HTTP ヘッダーを AJAX リクエストに追加します (例:X-Requested-With: XMLHttpRequest )、サーバー側でこのヘッダーの存在と値を確認します。 JavaScript は XMLHttpRequest のヘッダーを自由に設定できますが、通常のフォーム送信では設定できないため、これによりスクリプトによって開始されたリクエストを区別できます。

サンプルコード (CSRF トークンの実装):

サーバー側 (擬似コード):

// 生成并设置Token
function generateCsrfToken() {
    return crypto.randomBytes(32).toString('hex');
}

app.post('/login', (req, res) => {
    const token = generateCsrfToken();
    res.cookie('csrfToken', token, { httpOnly: true, secure: true, sameSite: 'strict' });
    // 存储token到session或其他存储机制
});

app.post('/submitForm', (req, res) => {
    if (req.body.csrfToken === req.cookies.csrfToken) {
        // 请求合法,处理逻辑...
    } else {
        // CSRF攻击检测,拒绝请求
        res.status(403).send('Forbidden');
    }
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

フロントエンドHTML:

<form action="/submitForm" method="POST">
    <!-- 其他表单字段... -->
    <input type="hidden" name="csrfToken" value="{{csrfToken}}">
    <button type="submit">Submit</button>
</form>
  • 1
  • 2
  • 3
  • 4
  • 5

上記のコードは単なる例であり、実際のアプリケーションは使用するバックエンド フレームワークと言語に応じて調整する必要があることに注意してください。