Web アプリケーションのセキュリティを高めるには、HTTP レスポンスヘッダーを適切に設定することが重要である。Flask でセキュリティヘッダーを設定する方法を解説する。
after_request で設定
@app.after_request
def add_security_headers(response):
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-XSS-Protection'] = '1; mode=block'
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
return response
主要なセキュリティヘッダー
| X-Content-Type-Options | MIME タイプのスニッフィングを防止 |
| X-Frame-Options | クリックジャッキング対策 |
| X-XSS-Protection | ブラウザの XSS フィルタを有効化 |
| Strict-Transport-Security | HTTPS を強制 |
| Content-Security-Policy | 読み込めるリソースを制限 |
Content-Security-Policy (CSP)
CSP は XSS 攻撃を防ぐ強力な仕組みである。
@app.after_request
def add_csp_header(response):
csp = (
"default-src 'self'; "
"script-src 'self' https://cdn.example.com; "
"style-src 'self' 'unsafe-inline'; "
"img-src 'self' data: https:; "
"font-src 'self' https://fonts.gstatic.com; "
"connect-src 'self' https://api.example.com; "
"frame-ancestors 'none';"
)
response.headers['Content-Security-Policy'] = csp
return response
Flask-Talisman の利用
Flask-Talisman を使えば、セキュリティヘッダーを簡単に設定できる。
pip install flask-talisman
from flask_talisman import Talisman
talisman = Talisman(
app,
force_https=True,
strict_transport_security=True,
session_cookie_secure=True,
content_security_policy={
'default-src': "'self'",
'script-src': ["'self'", 'cdn.example.com'],
'style-src': ["'self'", "'unsafe-inline'"],
}
)
開発環境での注意
HTTPS 強制は開発環境では問題になる。
if app.config['ENV'] == 'production':
Talisman(app, force_https=True)
else:
Talisman(app, force_https=False)
Cookie のセキュリティ設定
app.config['SESSION_COOKIE_SECURE'] = True # HTTPS でのみ送信
app.config['SESSION_COOKIE_HTTPONLY'] = True # JavaScript からアクセス不可
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax' # クロスサイトリクエストで送信しない
Referrer-Policy
response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
同一オリジンでは完全な URL を、クロスオリジンではオリジンのみを送信する。
Permissions-Policy
ブラウザの機能(カメラ、マイク、位置情報など)へのアクセスを制限する。
response.headers['Permissions-Policy'] = (
'geolocation=(), '
'microphone=(), '
'camera=()'
)
セキュリティヘッダーを適切に設定することで、多くの攻撃ベクトルを事前に防ぐことができる。