GET for POST

概要

  • 脆弱性の名前: GET for POST
  • どんな問題か: 本来POSTメソッドを使用すべき処理にGETメソッドが使用されている状態。
  • よくある発生シーン: Web APIの実装、フォームの送信処理、リダイレクト処理。

背景

  • 問題視されるようになった背景: Webアプリケーションの複雑化に伴い、開発者がHTTPメソッドの適切な使用を誤ることが増えたため。また、RESTful APIの設計原則が浸透しておらず、GETメソッドをデータの更新処理に使用してしまうケースが見られる。
  • クラウド設計や設定ミスによる実例: クラウド環境でAPI Gatewayを使用している場合、GETリクエストをバックエンドのPOSTエンドポイントに誤ってルーティングしてしまう設定ミスが発生することがある。

セキュリティ上のリスク

  • どんな攻撃に悪用されるか:
    • CSRF (Cross-Site Request Forgery) 攻撃: GETリクエストはURLにパラメータが含まれるため、攻撃者は悪意のあるWebサイトやメールを通じて、ユーザーに意図しない操作を実行させることができる。
    • 情報漏洩: GETリクエストのパラメータはURLに含まれ、ブラウザの履歴やサーバーのログに記録されるため、機密情報が漏洩する可能性がある。
    • キャッシュポイズニング: GETリクエストはキャッシュされる可能性があるため、機密情報がキャッシュに保存され、意図しないユーザーに情報が漏洩する可能性がある。
  • 実被害が出た具体的なインシデント: 具体的なインシデントは特定できませんでしたが、過去には、銀行の振込処理にGETメソッドが使用され、CSRF攻撃によって不正な振込が行われた事例が報告されています。

対処方法の具体例

PHPでの対処

<?php
// POSTリクエストのみを受け付ける
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405); // Method Not Allowed
    header('Content-Type: application/json');
    echo json_encode(['error' => 'Method Not Allowed']);
    exit;
}

// フォームの例
?>
<form method="POST" action="/submit">
    <input type="hidden" name="csrf_token" value="<?php echo generateToken(); ?>">
    <input type="password" name="password">
    <button type="submit">送信</button>
</form>

JavaScriptでの対処

// フォーム送信の制御
const form = document.querySelector('form');
form.addEventListener('submit', async (e) => {
    e.preventDefault();

    const formData = new FormData(form);
    try {
        const response = await fetch('/api/endpoint', {
            method: 'POST',
            body: formData,
            headers: {
                'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content
            }
        });
        const data = await response.json();
        console.log('Success:', data);
    } catch (error) {
        console.error('Error:', error);
    }
});

Pythonでの対処 (Flask)

from flask import request, jsonify

@app.route('/api/endpoint', methods=['POST'])
def handle_data():
    if request.method != 'POST':
        return jsonify({'error': 'Method Not Allowed'}), 405

    data = request.get_json()
    # POSTリクエストの処理
    return jsonify({'status': 'success'})

ベストプラクティス

  • HTTPメソッドの適切な使用: データの作成、更新、削除などの処理には、必ずPOST、PUT、DELETEなどの適切なHTTPメソッドを使用する。
  • サーバーサイドでの検証: サーバーサイドで、リクエストのHTTPメソッドを検証し、不正なメソッドが使用された場合はエラーを返す。
  • CSRF対策: フォームにはCSRFトークンを埋め込み、POSTリクエストの正当性を検証する。
  • リダイレクト処理の注意: リダイレクト時に機密情報をURLに含めないようにする。POSTリクエスト後にリダイレクトする場合は、303 See Otherステータスコードを使用する。

検出方法

  • OWASP ZAPでの検出時の出力例: OWASP ZAPでは、POSTメソッドを使用すべきエンドポイントに対してGETリクエストが送信された場合に、警告を表示する。
  • 手動での確認: ブラウザの開発者ツールを使用し、ネットワークリクエストを監視し、不適切なHTTPメソッドが使用されていないかを確認する。また、curlコマンドを使用して、GETリクエストを送信し、サーバーの応答を確認する。

まとめ

  • 重要度: Medium (機密情報の種類やWebサイトの構成によって変動します)
  • 運用チームや開発者が意識すべきポイント:
    • HTTPメソッドの適切な使用を徹底する
    • サーバーサイドでの検証を実装する
    • CSRF対策を実装する
    • リダイレクト処理に注意する
  • 再発防止の観点:
    • 開発者向けのHTTPメソッドに関するトレーニングを実施する
    • WebアプリケーションフレームワークのHTTPメソッドに関する設定を確認する
    • API Gatewayなどの設定ミスを防ぐためのIaC (Infrastructure as Code) ポリシーを導入する

補足資料リンクや参考URL

この解説記事が、脆弱性理解の一助となれば幸いです。