説明
ブラウザーがCookieなどの認証情報を自動送信するリクエストで、送信元検証やCSRF対策が不足すると、攻撃者が別のサイトからユーザーの権限で意図しないリクエストを送る可能性があります。Originの検証はユーザー認証の代わりにはなりません。ブラウザー以外のクライアントは、このヘッダーを自分で指定できます。
想定される影響
- CSRF: 攻撃者がユーザーに代わって悪意のあるリクエストを送り、不正アクセスを試みる可能性があります。
- 情報漏えい: リクエストによって情報の公開や転送の設定が変わると、機密情報が漏えいするおそれがあります。
- データの改ざん: 攻撃者がデータを変更し、システムの完全性を損なう可能性があります。
対処方法
- サーバー側で送信元のスキーム、ホスト、ポートを正確な許可リストと比較してください。
Originヘッダーがない場合と、送信元がnullの場合の扱いも決めてください。 - ブラウザーのCookie認証を使う状態変更リクエストには、フレームワークのCSRFトークン検証を適用してください。
- CORSでは、信頼する送信元だけにレスポンスの読み取りを許可してください。CORSだけでCSRF対策や認証・権限確認を置き換えないでください。
例
Cookie認証を使うリクエスト処理の抜粋です。認証と権限確認は別途適用してください。Flaskのyour_secret_key環境変数には、十分な乱数性を持つシークレットを事前に供給し、クライアントから有効なCSRFトークンを送る必要があります。
Django
変更前
python
# Djangoの変更前の例
from django.http import HttpResponse
def my_view(request):
if request.method == 'POST':
# CSRF検証なしでリクエストを処理
return HttpResponse("Request processed")
変更後
python
# Djangoの変更後の例
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect
@csrf_protect
def my_view(request):
if request.method == 'POST':
# CSRFトークンを検証してリクエストを処理
return HttpResponse("Request processed")
説明:
- 変更前: この抜粋にはCSRF対策が示されていません。他の層でも保護されていないCookie認証のリクエストは、CSRF攻撃にさらされる可能性があります。
- 変更後:
@csrf_protectでCSRF検証を適用します。変更前でもCsrfViewMiddlewareが有効なら保護される場合があるため、デコレーターがないことだけでは判断できません。
Flask
変更前
python
# Flaskの変更前の例
from flask import Flask, request
app = Flask(__name__)
@app.route('/submit', methods=['POST'])
def submit():
# CSRF検証なしでリクエストを処理
return "Request processed"
変更後
python
# Flaskの変更後の例
import os
from flask import Flask, request
from flask_wtf.csrf import CSRFProtect
app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv("your_secret_key").encode()
csrf = CSRFProtect(app)
@app.route('/submit', methods=['POST'])
def submit():
return "Request processed"
説明:
- 変更前: この抜粋にはCSRF対策が示されていません。他の層でも保護されていないCookie認証のリクエストは、CSRF攻撃にさらされる可能性があります。
- 変更後:
flask_wtf.csrf.CSRFProtectでCSRFトークンを検証します。
FastAPI
変更前
python
# FastAPIの変更前の例
from fastapi import FastAPI, Request
app = FastAPI()
@app.post("/submit")
async def submit(request: Request):
# CSRF検証なしでリクエストを処理
return {"message": "Request processed"}
変更後
python
# FastAPIの変更後の例
from fastapi import FastAPI, Request, HTTPException
from starlette.middleware.trustedhost import TrustedHostMiddleware
app = FastAPI()
# 信頼するホストを設定
app.add_middleware(
TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
)
@app.post("/submit")
async def submit(request: Request):
origin = request.headers.get('origin')
if origin not in ["https://example.com", "https://www.example.com"]:
raise HTTPException(status_code=403, detail="Invalid origin")
# リクエストを処理
return {"message": "Request processed"}
説明:
- 変更前: この抜粋にはCSRF対策が示されていません。他の層でも保護されていないCookie認証のリクエストは、CSRF攻撃にさらされる可能性があります。
- 変更後:
Originがない場合や許可リストにない値を拒否します。TrustedHostMiddlewareは宛先のHostを確認する別の機能であり、CSRF対策を置き換えるものではありません。