【実務・中級編】Cross-Origin Resource Sharing (CORS) の安全なポリシー設定 – アプリケーションセキュリティ & 安全な開発防御ガイド

CORSの「ワイルドカード」という名の時限爆弾:なぜあなたのAPIは無防備なのか

現場でコードレビューをしていると、今でもたまに目にするのが `Access-Control-Allow-Origin: ` という記述だ。「とりあえず外部サイトからAPIを叩けるようにしておこう」という安易な妥協が、実はセキュリティのドアを全開にしていることに気づいていないエンジニアが多すぎる。

CORS(Cross-Origin Resource Sharing)の設定を誤るということは、「誰でもあなたの認証済みセッションを悪用できる権限を与える」と同義だ。今日は、この甘い設定が引き起こす悲劇と、それを実務レベルでどう封じ込めるかを徹底的に叩き込む。

1. なぜ `Access-Control-Allow-Origin: ` が悪手なのか

ブラウザの同一オリジンポリシー(SOP)を回避するためのCORSだが、これを「すべて許可」に設定すると、悪意のあるサイト(攻撃者の攻撃サーバー)から、あなたのAPIに対して「認証情報付きのリクエスト」が送られた際、ブラウザは「ああ、許可されているなら送信してもいいんだな」と勘違いし、ユーザーのCookieや認証トークンを勝手に付与して送信してしまう。

攻撃シナリオ(PoCの概念)

1. 標的: ログイン中のユーザーが `bank.com` を利用している。
2. 攻撃: 攻撃者が作成した `evil-site.com` にユーザーを誘導する。
3. 実行: `evil-site.com` のスクリプトが `bank.com/api/transfer` を叩く。
4. 結末: `Access-Control-Allow-Origin: ` が設定されていると、ブラウザはユーザーのセッションCookieを添えて攻撃者のリクエストを通してしまう。ユーザーの預金が勝手に送金される、といった事態が現実的に起こり得る。

これを防ぐには、「信頼できるオリジン」をサーバーサイドで動的に判定するホワイトリスト方式が鉄則だ。

2. 【実装編】セキュアなCORSポリシーの書き方

「とりあえず設定ファイルで “ を書く」という手抜きをやめ、アプリケーション層またはWebサーバー層で厳密な検証を行う。

PHPでの実装例(ホワイトリスト方式)

フロントエンドのドメインを配列で管理し、リクエストヘッダーの `Origin` が一致する場合のみ許可を返す。

Nginxでの設定例

Nginxで制御する場合は、`map` ディレクティブを使うのが最もスマートだ。

map $http_origin $cors_origin {
default “”;
“https://app.example.com” $http_origin;
“https://partner.example.com” $http_origin;
}

server {
location /api/ {
# ホワイトリストに合致した場合のみヘッダーを付与
if ($cors_origin != “”) {
add_header ‘Access-Control-Allow-Origin’ $cors_origin always;
add_header ‘Access-Control-Allow-Credentials’ ‘true’ always;
add_header ‘Access-Control-Allow-Methods’ ‘GET, POST, OPTIONS’ always;
}

# プリフライトリクエストの処理
if ($request_method = ‘OPTIONS’) {
return 204;
}
}
}

3. セキュリティチーフからの「泥臭い」アドバイス

コードを書いて終わりではない。現場でよくある失敗を回避するためのチェックリストを置いておく。

  • `Access-Control-Allow-Credentials: true` と “ の併用は絶対に禁止:

ブラウザ側でエラーになるし、そもそも設計思想として矛盾している。Credentialsを許可するなら、必ず特定のオリジンを指定すること。

  • 「とりあえず開発環境だから」という言い訳を捨てる:

開発環境の設定がGit経由で本番に混入する事故は後を絶たない。環境変数でホワイトリストを管理し、本番環境では決して “ が有効にならない構成をCI/CDで担保せよ。

  • WAFの活用:

AWS WAFやCloudflareなどのエッジでCORSポリシーを管理するのも有効だ。アプリケーションコードを汚したくない場合は、インフラ層で「Originヘッダーの検証」を強制するルールを適用しよう。

最後に:防御は「疑うこと」から始まる

「便利さ」と「安全性」はしばしばトレードオフになる。しかし、CORSの設定に関しては、少しの手間で大きなリスクを排除できる。自分のコードが「誰からのリクエストを許可しているのか」を常に自問自答してほしい。

もし、今あなたのプロジェクトのコードに “ が混じっていたら、それは「泥棒に鍵を渡している」のと同じだ。今日、今すぐに修正しよう。それが、プロのエンジニアとしての最低限の矜持だ。

コメント

タイトルとURLをコピーしました