Featured image of post セキュリティヘッダーを調べ直した

セキュリティヘッダーを調べ直した

目次

背景

  • HTTPレスポンスに付けるセキュリティ系のヘッダーについて、断片的にしか理解していなかったので改めて調べ直した
  • 代表的な5つを中心に、それぞれ何を防いでいるのかを整理する

5つのセキュリティヘッダー

ヘッダー役割
CSP悪意のあるスクリプトを実行させない
HSTSHTTPS通信を強制して盗聴を防ぐ
frame-ancestors偽サイトに画面を埋め込ませない
X-Content-Type-Options: nosniffファイルを勝手にプログラムとして解釈させない
Referrer-Policy閲覧していたURLなどの情報漏れを減らす

CSP(Content-Security-Policy)

  • ページ内でスクリプト・スタイル・画像などを読み込んでよい取得元をホワイトリスト形式で指定するヘッダー
  • 主なディレクティブ
ディレクティブ制限対象
script-src実行してよいスクリプトの取得元
style-src適用してよいスタイルの取得元
img-src・connect-src・font-src画像・fetch通信・フォントの取得元
object-src 'none'Flash等のプラグインを無効化
base-uri<base>タグで指定できるURLを制限
  • script-srcにインラインスクリプトを許可しない設定にしておくと、攻撃者が入力フォームなどからscriptタグを注入できても実行されない、というのがXSS対策としての効果
  • 既存サイトに導入する場合、いきなりContent-Security-Policyで強制するとレイアウト崩れを起こしやすいため、違反のみ記録するContent-Security-Policy-Report-Onlyで様子を見てから本番適用するのが定石

HSTS(HTTP Strict Transport Security)

  • Strict-Transport-Security: max-age=31536000; includeSubDomains; preloadのように指定
  • 一度このヘッダーを受け取ったブラウザは、指定期間(max-age、秒単位)中は該当ドメインへの通信を常にHTTPSに置き換える
  • 効果があるのは「2回目以降のアクセス」で、初回アクセス時にHTTPで接続されてしまうと保護されない(この弱点を補うのがブラウザベンダー運営のpreloadリスト)
  • includeSubDomainsを付けるとサブドメインにも適用され、preloadはChromeなどに組み込まれているプリロードリストへの登録希望を示すフラグ

frame-ancestors

  • 自分のページを<iframe>や<frame>、<object>で埋め込んでよい親ページの取得元を指定するCSPのディレクティブ
  • 古くはX-Frame-Options(DENY・SAMEORIGIN・ALLOW-FROM)という専用ヘッダーで同様のことをしていたが、複数オリジンを許可できないなど柔軟性に欠けるため、現在はCSPのframe-ancestorsに統合されている
  • これを設定していないと、自サイトを透明なiframeで覆われて別サイトのボタンだと思わせてクリックさせる「クリックジャッキング」を防げない

X-Content-Type-Options: nosniff

  • ブラウザはContent-Typeが曖昧だったり省略されていたりすると、実際のバイト列を見て種類を推測する「MIMEスニッフィング」という挙動を持つ
  • この挙動を悪用すると、Content-Type: text/plainで配信しているはずのファイルが、中身次第でHTMLやJavaScriptとしてブラウザに解釈されてしまうことがある
  • X-Content-Type-Options: nosniffを付けると、このスニッフィングを無効化し、サーバーが宣言したContent-Typeどおりにのみ扱わせられる

Referrer-Policy

  • ページ遷移やサブリソース取得の際にブラウザが送るRefererヘッダー(直前にいたページのURL)の送り方を制御する
  • 主な値
値挙動
no-referrer一切送らない
same-origin同一オリジンへの遷移時のみ送る
strict-origin-when-cross-originクロスオリジンへはオリジンのみ送り、HTTPSからHTTPへのダウングレード時は送らない(多くのブラウザの現在のデフォルト)
  • Refererにトークン付きのURLやユーザー固有のパスが含まれていると、リンク先の第三者サイトにその情報がそのまま渡ってしまうため、指定しておく意味がある

自分のサイトでの設定状況

実際にm1ke.orgへcurlでアクセスして、レスポンスヘッダーを確認してみた。

1
curl -s -D - -o /dev/null https://www.m1ke.org/
1
2
3
4
HTTP/2 200
strict-transport-security: max-age=31536000
server: Netlify
...
  • HSTSはNetlifyがデフォルトで付与しており、既に有効になっていた
  • CSP・frame-ancestors・X-Content-Type-Options・Referrer-Policyはいずれも未設定
  • Netlifyではnetlify.tomlに[[headers]]セクションを追加するか、static/_headersファイルを置くことでレスポンスヘッダーをカスタマイズできるので、必要であれば次はそちらを設定する

まとめ

  • CSP・HSTS・frame-ancestors・X-Content-Type-Options・Referrer-Policyの5つは、いずれも「ブラウザに対して追加の制約を指示する」という共通点を持つヘッダーで、XSS・盗聴・クリックジャッキング・MIMEスニッフィング・リファラ経由の情報漏れといった、それぞれ異なる攻撃経路に対応している
  • 自分のサイトではHSTS以外はまだ未設定だったので、静的サイトであることも踏まえて優先度の高いものからnetlify.tomlで追加を検討したい。
Built with Hugo
テーマ Stack は Jimmy によって設計されています。