HTTPS と HTTP Strict Transport Security で悪意のある中間者を混乱させる

インターネットという巨大なパイプラインを流れる個人データの量を考えると、暗号化は軽視できるものではありません。最新のブラウザには、転送中のユーザーデータの安全性を確保するために使用できるメカニズムがいくつか用意されています。セキュア Cookie と Strict Transport Security は、その中でも特に重要な 2 つのメカニズムです。これにより、ユーザーをシームレスに保護し、接続を 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 ハンドシェイクを開始して安全なチャネルを作成すると、サーバーは証明書を提供します。この証明書は、サーバーが適切な秘密鍵を所有していることを確認して、サーバーの 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 プロトコルを介して、ユーザーにシームレスなログイン エクスペリエンスを提供できます。セッション ID などの機密情報を含む Cookie に保存されたデータは、すべてのリクエストとともに送信されるため、サーバーは現在どのユーザーに応答しているかを把握できます。ユーザーが HTTPS 経由でサイトにアクセスしていることを確認したら、Cookie に保存されている機密データが安全な接続を介してのみ転送され、平文で送信されないようにする必要もあります。

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

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

1 つのキーワードを追加することで、Cookie の使用をセキュアなセッションに制限するようブラウザに指示できます。

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 の最近の記事「Securing your Web Server with SSL/TLS」は、サーバー設定の基本について、より詳しい背景情報を得るのに役立ちます。
  • HTTP Strict Transport Security 仕様(RFC6797)には、Strict-Transport-Security ヘッダーに関する技術情報がすべて記載されています。
  • 作業内容を十分に理解したら、次のステップとして、特定の証明書セットを介してのみサイトにアクセスできるようにすることをアドバタイズします。IETF では、Public-Key-Pins ヘッダーを介してこれを実現できるようにする作業が進められています。まだ初期段階ですが、興味深く、注目に値します。