HTTPS と HTTP Strict Transport Security で悪意のあるミドルマンを混乱させる

インターネットという巨大なパイプラインを流れる個人データの量を考えると、暗号化は軽視できない、軽視すべきではないものです。最新のブラウザには、転送中のユーザーデータを安全に保つために使用できるいくつかのメカニズムがあります。その中で最も重要なのが、セキュア クッキー厳格な転送セキュリティです。これらの機能を使用すると、ユーザーをシームレスに保護し、接続を HTTPS にアップグレードして、ユーザーデータがクリアテキストで送信されることがないようにすることができます。

なぜ重要か次のことを検討してください。

暗号化されていない HTTP 接続経由でウェブページを配信することは、郵便局に向かっているように見える通りで最初に出会った人に未開封の封筒を手渡すのとほぼ同じです。運が良ければ、その人が目的地まで運んでくれるかもしれません。運が悪ければ、その人が次の目的地に向かう人を見つけて、その人に渡すかもしれません。そのユーザーも同じことをするかもしれません。

この即席のチェーンに参加する見知らぬ人のほとんどは信頼できる人物であり、公開状を覗いたり、変更したりすることはありません。ただし、手紙が何度もやり取りされるほど、送信する手紙に完全にアクセスできる人の数は多くなります。最終的には、宛先に何かが届く可能性は非常に高いですが、その何かが最初に渡したものと同じかどうかは不明です。封筒を密封しておけばよかったのに...

仲介者

良いか悪いかは別として、インターネットの大部分は見知らぬ人の信頼性に依存しています。サーバーは相互に直接接続されておらず、巨大な電話回線ゲームのように、リクエストとレスポンスをルーターからルーターに渡します。

これらのホップは、traceroute で確認できます。パソコンから HTML5Rocks へのルートは次のようになります。

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 ホップは決して悪い値ではありません。ただし、HTTP 経由でリクエストを送信する場合、これらの中間ルータはそれぞれ、リクエストとサーバーのレスポンスに完全にアクセスできます。すべてのデータは暗号化されていないプレーンテキストとして転送されます。これらの仲介業者は、中間者攻撃として機能し、データを読み取ったり、転送中にデータを操作したりする可能性があります。

さらに悪いことに、この種の傍受は実質的に検出できません。悪意を持って変更された HTTP レスポンスは、受信したデータが送信されたデータと完全に一致することを確認できるメカニズムがないため、有効なレスポンスとまったく同じに見えます。誰かがいたずらでインターネットをひっくり返すと、どうしようもありません。

安全な回線ですか?

平文の HTTP から安全な HTTPS 接続に切り替えると、仲介者に対する最善の防御策となります。HTTPS 接続では、データが送信される前にチャネル全体がエンドツーエンドで暗号化されるため、送信元と宛先の間にあるマシンが転送中のデータを読み取ったり変更したりすることはできません。

Chrome のアドレスバーには、接続のステータスに関する詳細情報が表示されます。
Chrome のアドレスバーには、接続のステータスに関する詳細情報が表示されます。

HTTPS が提供するセキュリティは、公開鍵と秘密鍵の概念に基づいています。詳細については、この記事では説明しません(幸い、この記事の範囲を超えています)。ただし、基本的な前提は非常に単純です。特定の公開鍵で暗号化されたデータは、対応する秘密鍵でのみ復号できます。ブラウザが HTTPS handshake を開始して安全なチャネルを作成すると、サーバーは証明書を提供します。この証明書には、サーバーが適切な秘密鍵を保持していることを確認して ID を検証するために必要なすべての情報が含まれています。以降の通信はすべて、リクエストが認証済みサーバーに送信され、レスポンスが認証済みサーバーから受信されたことを証明するように暗号化されます。

したがって、HTTPS を使用すると、通信相手が想定どおりのサーバーであり、他の誰かが盗聴したり、ワイヤー上のビットを操作したりしていないことをある程度保証できます。この種の暗号化は、ウェブ上のセキュリティを確保するための絶対的な前提条件です。アプリケーションが現在 HTTPS 経由で配信されていない場合は、攻撃に対して脆弱です。修正してください。Ars Technica には、証明書を取得してインストールする(無料)という優れたガイドがあります。技術的な詳細については、こちらをご覧ください。構成はプロバイダやサーバーによって異なりますが、証明書リクエストのプロセスはどこでも同じです。

デフォルトで保護

証明書をリクエストしてインストールしたら、ユーザーがその成果を享受できるようにします。HTTP リダイレクトを使って既存のユーザーを HTTPS 接続にシームレスに移行し、Cookie が安全な接続経由でのみ配信されるようにします。

こちらへ

ユーザーが http://example.com/ にアクセスしたときに、適切な Location ヘッダーを使用して 301 Moved Permanently レスポンスを送信し、https://example.com/ にリダイレクトします。

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

この種のリダイレクトは、Apache や Nginx などのサーバーで簡単に設定できます。たとえば、http://example.com/ から https://example.com/ にリダイレクトする Nginx 構成は次のようになります。

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

Cookie を使用すると、ステートレス HTTP プロトコル経由で、ユーザーにシームレスなログイン エクスペリエンスを提供できます。Cookie に保存されているデータ(セッション ID などの機密情報を含む)は、すべてのリクエストとともに送信されるため、サーバーは現在対応しているユーザーを把握できます。ユーザーが HTTPS 経由でサイトにアクセスしていることを確認したら、Cookie に保存されている機密データが安全な接続経由でのみ転送され、クリアテキストで送信されないようにする必要があります。

通常、Cookie の設定には次のような HTTP ヘッダーが関与します。

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

セッションを保護するために Cookie の使用を制限するようにブラウザに指示するには、1 つのキーワードを追加します。

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

secure キーワードで設定された Cookie は、HTTP 経由で送信されることはありません。

開いているウィンドウを閉じる

HTTPS への透過的なリダイレクトとは、ユーザーがサイトにアクセスしているほとんどの時間を、安全な接続で過ごせることを意味します。ただし、攻撃の機会がわずかながら残ります。最初の HTTP 接続は完全に開いており、SSL ストリッピングや関連する攻撃に対して脆弱です。中間者は最初の HTTP リクエストに完全にアクセスできるため、ユーザーとサーバー間のプロキシとして機能し、サーバーの意図に関係なく、安全でない HTTP 接続を維持できます。

この種の攻撃のリスクを軽減するには、ブラウザに HTTP Strict Transport Security(HSTS)の適用を依頼します。Strict-Transport-Security HTTP ヘッダーを送信すると、ネットワークにアクセスすることなく、ブラウザに HTTP から HTTPS へのリダイレクトをクライアントサイドで行うよう指示します(これはパフォーマンスにも優れています。リクエストを送信しなくて済むのが最善のリクエストです)。

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

このヘッダーをサポートするブラウザ(現在は Firefox、Chrome、Opera: caniuse に詳細)では、この特定のサイトが HTTPS のみのアクセスをリクエストしたことがメモされます。つまり、ユーザーがサイトにアクセスする方法に関係なく、HTTPS 経由でアクセスすることになります。ブラウザに http://example.com/ と入力しても、HTTP 接続をせずに HTTPS に移動します。さらに、ブラウザが無効な証明書を検出した場合(サーバーの ID のなりすましを試みている可能性がある場合)、ユーザーは HTTP 経由で続行できなくなります。すべてまたは何もないという、優れた仕組みです。

ブラウザは、max-age 秒(この例では約 1 か月)後にサーバーの HSTS ステータスを期限切れにする。この値は、適度に長い値に設定します。

また、includeSubDomains ディレクティブをヘッダーに追加することで、オリジンのサブドメインをすべて保護することもできます。

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

安全に進む

HTTPS は、送信したデータが目的の受信者に完全に届くことをある程度確実にできる唯一の方法です。サイトとアプリケーションの安全な接続を今すぐ設定する必要があります。手順は非常に簡単で、お客様のデータを安全に保つのに役立ちます。暗号化されたチャネルを設定したら、301 HTTP レスポンスを発行して、ユーザーがサイトにアクセスした方法に関係なく、この安全な接続にユーザーを透過的にリダイレクトする必要があります。次に、Cookie の設定時に secure キーワードを追加して、すべてのユーザーの機密性の高いセッション情報がその安全な接続のみを使用するようにします。これらの設定が完了したら、ユーザーが誤ってバスから落ちないようにします。ブラウザが Strict-Transport-Security ヘッダーを送信して適切に動作するようにすることで、ユーザーを保護します。

HTTPS の設定は難しくなく、サイトとそのユーザーに大きなメリットをもたらします。ぜひお試しください。

リソース

  • StartSSL は、ドメイン所有権確認済みの無料証明書を提供しています。無料は魅力的です。もちろん、より高いレベルの確認も可能で、料金も手頃です。
  • SSL サーバー テスト: サーバーの HTTPS を設定したら、SSL Labs のサーバー テストを実行して、正しく設定されていることを確認します。詳細なレポートが生成され、実際に稼働しているかどうかを確認できます。
  • サーバー設定の詳細については、Ars Technica の最新記事「SSL/TLS でウェブサーバーを保護する」をご覧ください。
  • HTTP Strict Transport Security 仕様(RFC6797)では、Strict-Transport-Security ヘッダーに関するすべての技術情報を確認できます。
  • 何をすべきかを理解したら、次のステップとして、サイトにアクセスできるのは特定の証明書セットのみであることを宣言できます。IETF では、Public-Key-Pins ヘッダーを介してこれを実現するための作業が進められています。まだ初期段階ですが、興味深い内容であり、注目に値します。