HTTPレスポンスヘッダーを分割攻撃から保護する
説明
HTTPレスポンス分割は、応答ヘッダーに改行文字を挿入して応答を分割し、攻撃者が操作した出力を追加する攻撃です。フレームワークやサーバーが改行を許容すると、XSSやキャッシュ汚染につながるおそれがあります。DjangoとWerkzeugはヘッダー内の改行を拒否するため、以下の未検証の例が直ちにレスポンス分割を許すわけではありません。不正な入力で例外が発生することがあります。
想定される影響
- XSS: 挿入されたスクリプトがクライアントで実行される可能性があります。
- キャッシュ汚染: 悪意ある内容がキャッシュされ、他の利用者に配信されるおそれがあります。
- 情報漏えい: 改ざんされた応答で機密情報が漏えいする可能性があります。
対処方法
- ヘッダーに入れる入力を検証し、改行文字(
\r、\n)を除去します。 - フレームワークのAPIでヘッダーを設定し、改行文字が拒否されることを確認します。
例
Django
変更前
python
# Djangoで入力を検証しない例
from django.http import HttpResponse
def unsafe_view(request):
user_input = request.GET.get('input', '')
response = HttpResponse()
response['X-My-Header'] = user_input
return response
変更後
python
# Djangoで改行を除去する例
from django.http import HttpResponse
import re
def safe_view(request):
user_input = request.GET.get('input', '')
sanitized_input = re.sub(r'[\r\n]', '', user_input)
response = HttpResponse()
response['X-My-Header'] = sanitized_input
return response
解説:
- 変更前: 入力をそのままヘッダーに渡します。改行を許容するかどうかによって、エラーやヘッダー挿入のリスクが生じます。
- 変更後: ヘッダーを設定する前に改行を除去します。実際のヘッダーの用途に合った値の検証も必要です。
Flask
変更前
python
# Flaskで入力を検証しない例
from flask import Flask, request, Response
app = Flask(__name__)
@app.route('/unsafe')
def unsafe():
user_input = request.args.get('input', '')
response = Response()
response.headers['X-My-Header'] = user_input
return response
変更後
python
# Flaskで改行を除去する例
from flask import Flask, request, Response
import re
app = Flask(__name__)
@app.route('/safe')
def safe():
user_input = request.args.get('input', '')
sanitized_input = re.sub(r'[\r\n]', '', user_input)
response = Response()
response.headers['X-My-Header'] = sanitized_input
return response
解説:
- 変更前: 入力をそのままヘッダーに渡します。改行を許容するかどうかによって、エラーやヘッダー挿入のリスクが生じます。
- 変更後: ヘッダーを設定する前に改行を除去します。実際のヘッダーの用途に合った値の検証も必要です。
FastAPI
変更前
python
# FastAPIで入力を検証しない例
from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.get("/unsafe")
async def unsafe(request: Request):
user_input = request.query_params.get('input', '')
response = Response()
response.headers['X-My-Header'] = user_input
return response
変更後
python
# FastAPIで改行を除去する例
from fastapi import FastAPI, Request, Response
import re
app = FastAPI()
@app.get("/safe")
async def safe(request: Request):
user_input = request.query_params.get('input', '')
sanitized_input = re.sub(r'[\r\n]', '', user_input)
response = Response()
response.headers['X-My-Header'] = sanitized_input
return response
解説:
- 変更前: 入力をそのままヘッダーに渡します。改行を許容するかどうかによって、エラーやヘッダー挿入のリスクが生じます。
- 変更後: ヘッダーを設定する前に改行を除去します。実際のヘッダーの用途に合った値の検証も必要です。
参考資料
- OWASP: HTTPレスポンス分割
- CWE: CWE-113: HTTPヘッダー内のCRLFの不適切な無害化