ブラウザでリファラーを無効にすることについて HTTP 仕様はなんと言っているか

<a href> によるアンカーや <form action> によるフォーム送信でページ遷移が行われた場合、多くのケースではリファラーが送られます。実際にどんな値が送信されるかはReferrer Policy(www.w3.org)によって異なり、デフォルトの挙動は長らく no-referrer-when-downgrade(HTTPS→HTTPの時を除き、完全なURLを送る)でしたが、最近のブラウザは strict-origin-when-cross-origin(HTTPS→HTTPの時を除き、 same-origin request 時は完全な URL を、 cross-origin request 時は origin データのみを送る)になりつつあります。

リファラーを無効にしたいケース

一方で、主にプライバシー面からリファラーの送信を制御したいというユーザーの欲求は以前からありました。一昔前は Google などの検索結果ページからリンク先に飛ぶと、検索結果ページの URL がリファラーとして当該サイトのアクセスログに記録され、そこには ?q=hogehoge のような形で検索キーワードが含まれていたため、「どんなキーワードでこのページに辿り着いたか」がアクセスログから分かってしまうということがありました。多くの場合は「なんとなく気持ち悪い」「恥ずかしい」程度で済むでしょうが、例えば企業内のネットワークから一般人の個人名を検索した場合はどうでしょう。

ある人が企業に就職し、「本日入社した○○です、よろしくお願いします」という挨拶を社内メールで一斉送信、他の社員が好奇心からその名前を Web 検索したとします。すると、検索結果の上位に表示されるサイトの管理者は、アクセスログに記録された IP アドレスとリファラー情報から、そのタイミングでその会社とその個人に何らかの関係ができたと推察することが可能です。「田中太郎 入社」などと検索した人が複数いたら、「何らかの関係」どころか「入社したという事実」まで推察できてしまうかもしれません。本人が所属企業を公表していない場合、悪意のないただの検索であってもプライバシーの侵害になります。無論、個人名に限らず、取引先の会社名や告知前の新サービス名などでも同様です。

昨今では Google は検索結果ページからクエリー付きの URL がリファラーで飛ばないような技術的配慮がされていますが、サービスによっては今もリファラーから検索単語が分かってしまうものも存在します。そもそもが社内ネットワークから非公表の単語を外部サービスを使って検索するなという話ではあるのですが、かと言ってデスクワークの職種では「検索サービス全面禁止」は現実的ではありません。数ある対策の一つとして、個々人が「ブラウザの設定でリファラーを無効にする」は一定の緩和策にはなるでしょう。

ブラウザでリファラーを制御する方法

以前は設定画面から簡単にリファラーを無効にできるブラウザがありました。そう、みんな大好き Presto Opera です。

オリジナル画像
図1:Opera 12 の「詳細設定」画面。「ネットワーク」内に「リファラー情報を送信」のチェックボックスがある

現代では通常の設定画面から変更できるブラウザはおそらくないと思いますが、 Firefox では about:config 内にリファラーを制御する設定がいくつか存在します。

また、アドオンでは単に有効 / 無効の切替だけでなく、アクセスした URL と同じ文字列などに偽装できるようにしたり、ドメインごとにホワイトリストを設定できたりするなど、より細かく制御できるものも存在します。一律に無効にしてしまうと使えなくなってしまうサービスもありますから、このような高度な設定ができるアドオンの存在はありがたいです。

HTTP 仕様はなんと言っているか

RFC 2616 (1999年)

1999年に発行されたRFC 2616(datatracker.ietf.org)では、 Referer ヘッダのセキュリティ面の考察としてこんなことが書かれていました。

Because the source of a link might be private information or might reveal an otherwise private information source, it is strongly recommended that the user be able to select whether or not the Referer field is sent. For example, a browser client could have a toggle switch for browsing openly/anonymously, which would respectively enable/disable the sending of Referer and From information.

15.1.3 Encoding Sensitive Information in URI's(datatracker.ietf.org)

要約するとこんな感じです。

  • Referer フィールドを送出するかどうかの選択権はユーザーにある(ユーザーエージェントはその選択ができるようにすることを強く推奨する)
  • 例えばブラウザに openly / anonymously のトグルスイッチを設けることで、有効 / 無効に設定できる

このように、実際にリファラーを無効にできるブラウザが存在するだけでなく、 RFC としてもユーザーの意思次第でリファラーを無効にしても良いと明言していました。

RFC 7231 (2014年)

2014年に改定されたRFC 7231(datatracker.ietf.org)では、プライバシー面の記載が追加されました。

Most general-purpose user agents do not send the Referer header field when the referring resource is a local "file" or "data" URI. A user agent MUST NOT send a Referer header field in an unsecured HTTP request if the referring page was received with a secure protocol. See Section 9.4 for additional security considerations.

5.5.2. Referer(datatracker.ietf.org)
  • ほとんどのユーザーエージェントはローカルの filedata URI においてリファラーを送出しない
  • ユーザーエージェントはセキュアなプロトコルからセキュアでない HTTP リクエストに対してリファラーを送出してはならない

いずれも歴史的にブラウザは元々そういう挙動でしたからこれは真新しい情報ではなく、1999年以来長らく更新されていなかった RFC の記述が追従しただけのことです。

セキュリティ面では、 RFC 2616 に書かれていたリファラーを無効にする件についての記述がごっそり削除された一方で、 CSRF に関する言及が追加されています。

Some servers use the Referer header field as a means of denying links from other sites (so-called "deep linking") or restricting cross-site request forgery (CSRF), but not all requests contain it.

5.5.2. Referer(datatracker.ietf.org)

RFC 7231 では CSRF 対策としてリファラーの値を使用することについて、それが行われているサーバーもあるという事実を言っているに過ぎず、その是非までは踏み込んでいません。そこは RFC の範疇ではないということなのかもしれませんが、 Web アプリケーションの実装者として意識すべきは下記の2点だと思います。

  • 複数存在する CSRF 対策の一つとして、リファラーの値をチェックすることは安全上有効である
  • しかしながら、リファラーを無効にしている環境ではそのサービスを使えなくなってしまう

以下、関連書籍と記事を挙げておきます。

まとめ

  • プライバシーの面などからリファラーを無効にしたいケースは存在する。 Google の進化などにより、クリティカルな事故が起こりうる可能性は減ってきてはいるが、皆無になったわけではなく、現代でも、将来も、リファラーを無効にすることで安全性が向上するケースは引き続き存在する(※本質的な対策ではなく、緩和策に過ぎないことに注意)。
  • 2010年代中盤まではリファラーを無効にできるブラウザが存在した。当時の RFC でもブラウザがそのような機能を有することを推奨していた。
  • 現在はリファラーを無効にできるブラウザは消滅した。 RFC からもブラウザの機能に関する記述は削除された。ただし、引き続きアドオンなどで制御できる。
  • CSRF 対策としてリファラーをチェックする手法は安全上有効であるが、リファラーを無効にしている環境では利用できなくなってしまう。個人的には <input type="hidden"> にトークンを埋め込む手法を優先すべきと考える。