過度に許可されたCORS設定

信頼できない送信元がブラウザーの応答を読めるCORS設定を制限してください。

説明

CORSは、ブラウザーが別のオリジンからの応答を読める条件を定めます。未検証のOriginをAccess-Control-Allow-Originへそのまま反映すると、信頼できないサイトが応答を読める可能性があります。認証済みの応答が漏えいするかどうかは、ブラウザーの認証情報送信、Cookieポリシー、サーバーの認証情報許可設定にも依存します。CORSを許可しただけで、セッションCookieの値が相手のサイトへ送られるわけではありません。

想定される影響

  • 信頼できないサイトが機密性のあるAPI応答を読める可能性があります。
  • 認証情報付きリクエストが許可される条件では、被害者の権限で返されるデータが漏えいするおそれがあります。
  • CORSは認証・認可やCSRF対策の代わりにはならず、それぞれの保護も必要です。

対処方法

  1. 許可する送信元のスキーム、ホスト、ポートを明示的な許可リストで管理してください。
  2. HttpServletResponse.setHeader("Access-Control-Allow-Origin", userInput)のように未検証の入力を反映しないでください。公開する応答への意図的な*許可と、機密性のある応答を区別してください。
  3. 送信元によって応答ヘッダーが変わり、応答をキャッシュする場合はVary: Originも設定してください。認証情報は必要な送信元だけに許可し、認証・権限確認とCSRF対策を維持してください。

例

許可する送信元は実際のサービスに合わせてください。以下は応答ヘッダー設定の抜粋であり、プリフライトと認証情報のポリシーは別途構成する必要があります。

変更前

java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class InsecureCORS {
    public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String origin = request.getHeader("Origin"); // ユーザー入力に基づく設定
        response.setHeader("Access-Control-Allow-Origin", origin); // 未検証の送信元
    }
}

変更後

java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Set;

public class SecureCORS {
    private static final Set<String> ALLOWED_ORIGINS = Set.of(
        "https://example.com",
        "https://sub1.example.com",
        "https://sub2.example.com"
    );

    public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String origin = request.getHeader("Origin");

        if (origin != null && ALLOWED_ORIGINS.contains(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
        } else {
            response.setHeader("Access-Control-Allow-Origin", "https://example.com"); // 既定の許可する送信元
        }
    }
}

説明:

  • 変更前: ユーザー入力をAccess-Control-Allow-Originへ直接設定し、攻撃者の送信元を許可できてしまいます。
  • 変更後: 許可リストにある送信元だけを反映します。それ以外には固定の送信元を返すため、一致しない送信元からは応答を読めません。

参考資料