ブラウザ
 Computer >> コンピューター >  >> ソフトウェア >> ブラウザ

ブラウザはWebコンテンツをどう処理するのか?仕組みを徹底解説

ブラウザはWebコンテンツをどう処理するのか?仕組みを徹底解説

執筆:Alex Nadalin

Webアプリケーションセキュリティ入門

「Webアプリケーションセキュリティ」シリーズの幕開けとして、まずはブラウザが何をしているのか、どのようにそれを実現しているのかを解説します。ほとんどのユーザーはブラウザを通じてあなたのWebアプリケーションにアクセスするため、この素晴らしいソフトウェアの基本を理解することは不可欠です。

一言でいえば、ブラウザとはレンダリングエンジンです。その役割は、Webページをダウンロードし、人間が理解できる形で画面に描画すること。これはかなり乱暴な簡略化ですが、今のところはこれだけの知識で十分です。

  • ユーザーがアドレスバーにURLを入力する
  • ブラウザがそのURLの「ドキュメント」をダウンロードして描画する

Chrome、Firefox、Edge、Safariといった人気ブラウザを使い慣れているかもしれませんが、世の中には他にもさまざまなブラウザが存在します。

たとえばlynxは、コマンドライン上で動作する軽量のテキストベースブラウザです。その内部原理は「メインストリーム」なブラウザとまったく同じで、ユーザーがURLを入力し、ブラウザがドキュメントを取得して表示するという流れも変わりません。唯一異なるのは、視覚的なレンダリングエンジンではなくテキストインターフェースを使用している点です。そのため、Googleのようなサイトは次のように表示されます。

ブラウザはWebコンテンツをどう処理するのか?仕組みを徹底解説

ブラウザの大まかな役割は理解できましたが、次はこの賢いアプリケーションが私たちのために行っている処理を、もう少し詳しく見ていきましょう。

ブラウザは何をしているのか?

結論から言うと、ブラウザの主な仕事は以下の4つのステップで構成されています。

  • DNS解決(DNS resolution)
  • HTTP通信(HTTP exchange)
  • レンダリング(Rendering)
  • これらの繰り返し

DNS解決

このプロセスにより、ユーザーがURLを入力したときに、ブラウザは「どのサーバーに接続すべきか」を把握できます。ブラウザはDNSサーバーに問い合わせ、google.com216.58.207.110というIPアドレスに対応することを突き止めます。このIPアドレスこそが、ブラウザが実際に接続する先です。

HTTP通信

リクエストを受け持つサーバーを特定すると、ブラウザはそのサーバーとのTCP接続を確立し、HTTP通信(HTTP exchange)を開始します。これは要するに、ブラウザがサーバーに「何が必要か」を伝え、サーバーがそれに応答するための手段です。

HTTPとは、Web上で最も広く使われている通信プロトコルの名称にすぎません。ブラウザはサーバーとやり取りする際、主にHTTPを介して会話します。HTTP通信では、クライアント(ブラウザ)がリクエストを送信し、サーバーがレスポンスで応答します。

たとえば、ブラウザがgoogle.comの背後にあるサーバーへの接続に成功すると、次のようなリクエストを送ります。

GET / HTTP/1.1
Host: google.com
Accept: */*

このリクエストを行ごとに分解してみましょう。

  • GET / HTTP/1.1:最初の行で、ブラウザは「/の位置にあるドキュメントを取得してほしい」とサーバーに依頼しています。また、以降のリクエストがHTTP/1.1プロトコルに従うことも示しています(1.02が使われる場合もあります)
  • Host: google.com:これはHTTP/1.1で必須とされる唯一のHTTPヘッダーです。1台のサーバーが複数のドメイン(google.comgoogle.co.ukなど)を扱えるため、クライアントはここで「どのホスト宛てのリクエストか」を明示します
  • Accept: */*:任意のヘッダーで、「どんな形式のレスポンスでも受け入れます」とブラウザがサーバーに伝えています。同じリソースがJSON・XML・HTMLなど複数の形式で提供されている場合、サーバー側が好みの形式を選べるようにするものです

クライアントとして振る舞うブラウザがリクエストを送り終えると、今度はサーバーが応答する番です。レスポンスは次のような形になります。

HTTP/1.1 200 OK
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=1234; expires=Fri, 18-Jan-2019 18:25:04 GMT; path=/; domain=.google.com; HttpOnly

<!doctype html>
<html>
...
</html>

情報量が多くて圧倒されそうですね。サーバーは、リクエストが成功したこと(200 OK)を伝えるとともに、レスポンスにいくつかのヘッダーを付加しています。たとえば、どのサーバーがリクエストを処理したか(Server: gws)、このレスポンスのX-XSS-Protectionポリシーは何か、といった具合です。

現時点で、レスポンスの一行一行をすべて理解する必要はありません。HTTPプロトコルや各種ヘッダーの詳細については、このシリーズの後半で改めて扱います。

今は「クライアントとサーバーがHTTPを介して情報をやり取りしている」ということだけ押さえておきましょう。

レンダリング

最後に紹介するのがレンダリングのプロセスです。もしブラウザがユーザーに見せるのが奇妙な文字列の羅列だけだったら、まったく役に立ちませんよね。

レスポンスのボディには、Content-Typeヘッダーに従った形式でコンテンツが格納されています。今回の例ではコンテンツタイプがtext/htmlだったため、レスポンスにはHTMLマークアップが含まれているはずです。そしてボディを見ると、実際にまさにそれが入っています。

こここそが、ブラウザが真価を発揮する場面です。ブラウザはHTMLを解析し、マークアップ内に含まれる追加リソース(JavaScriptファイルやCSSドキュメントなど)を読み込み、それらをできるだけ早くユーザーに提示します。

こうして最終的に出来上がるのは、誰もが理解できる見た目のあるページです。

アドレスバーでEnterキーを押した瞬間に何が起きているのか、さらに詳しく知りたい方は、「What happens when…」という記事をおすすめします。このプロセスの裏側の仕組みを非常に丁寧に解説した試みです。

このシリーズはセキュリティがテーマなので、ここで重要なヒントをお伝えします。攻撃者は、HTTP通信とレンダリングの段階における脆弱性を容易に悪用して利益を得ています。脆弱性や悪意あるユーザーは他の層にも潜んでいますが、これらのレベルでのセキュリティ対策を強化するだけで、セキュリティ態勢の改善に大きく前進できるのです。

主要ブラウザのベンダー

最も人気のある4つのブラウザは、それぞれ異なるベンダーが開発しています。

  • Google製のChrome
  • Mozilla製のFirefox
  • Apple製のSafari
  • Microsoft製のEdge

ベンダーたちは市場シェアを競い合う一方で、ブラウザにとっての「最低要件」とも言えるWeb標準の向上に向けて協力し合ってもいます。

標準策定の中心組織はW3Cですが、各ブラウザが独自に実装した機能がやがてWeb標準になるケースも珍しくありません。セキュリティ分野も例外ではありません。

たとえばChrome 51ではSameSiteクッキーが導入されました。これは、CSRF(クロスサイトリクエストフォージェリ)として知られる特定の脆弱性からWebアプリケーションを守れるようにする機能です(詳細は後述)。他のベンダーもこれを優れたアイデアと判断して追随し、SameSiteはWeb標準となりました。現時点でSameSiteクッキー未対応の主要ブラウザはSafariのみです。

ここから読み取れる教訓は2つあります。

  • Safariはユーザーのセキュリティへの関心が薄いように見える(もちろん冗談です。SameSiteクッキーはSafari 12で利用可能になり、この記事を読む頃にはすでにリリースされているかもしれません)
  • あるブラウザの脆弱性を修正しても、すべてのユーザーが安全になったわけではない

1つ目はSafariへの皮肉(繰り返しますが冗談です!)ですが、2つ目は本当に重要なポイントです。Webアプリケーションを開発する際には、複数のブラウザで見た目を揃えるだけでなく、プラットフォームに関わらずユーザーが同等に保護されることも保証しなければなりません。

Webセキュリティへの戦略は、ブラウザベンダーが何を許容しているかによって変わるべきです。現在、ほとんどのブラウザは共通の機能セットをサポートし、ロードマップから大きく外れることは稀ですが、上記のような事例は今でも起こりえます。セキュリティ戦略を定義する際には、この点を考慮に入れる必要があります。

今回の例で言えば、CSRF対策をSameSiteクッキーだけで行うと決めたなら、Safariユーザーを危険に晒していることを自覚すべきです。そして、そのことはユーザー自身も知っておくべきでしょう。

最後にもう1つ。どのブラウザバージョンをサポートするかは自分で決められるという点も忘れてはいけません。すべてのバージョンをサポートするのは非現実的です(Internet Explorer 6を思い浮かべてください)。とはいえ、主要ブラウザの最新の数バージョンをサポートするのは概ね良い判断です。ただし、特定のプラットフォームで保護を提供しないのであれば、ユーザーにその旨を告知するのが望ましいでしょう。

プロのコツ:ユーザーに古いブラウザの使用を勧めたり、積極的にサポートしたりしてはいけません。あなたが万全の対策を講じていても、他の開発者はそうとは限りません。主要ブラウザの最新サポートバージョンの利用をユーザーに促しましょう。

ベンダーのバグか、標準のバグか?

一般ユーザーがサードパーティ製クライアント(=ブラウザ)経由でアプリケーションにアクセスするという事実は、安全なブラウジング体験の実現にもう一段階の不確定要素をもたらします。ブラウザ自体に脆弱性が存在する可能性があるのです。

ベンダーは通常、ブラウザ本体の脆弱性を発見したセキュリティ研究者に対して報奨金(いわゆるバグバウンティ)を支払います。これらのバグはあなたの実装ではなく、ブラウザ自身がセキュリティをどう処理するかに起因するものです。

たとえばChromeの報奨金プログラムでは、セキュリティエンジニアがChromeセキュリティチームに脆弱性を報告できます。報告された脆弱性が確認されれば、パッチが公開され、通常はセキュリティアドバイザリーが一般向けに発表され、研究者には(多くの場合金銭的な)報酬が支払われます。

Googleのような企業がバグバウンティプログラムに相応の資金を投じるのは、問題発見への金銭的インセンティブによって研究者を惹きつけ、結果としてソフトウェアのセキュリティ向上につながるからです。

バグバウンティプログラムでは全員が利益を得られます。ベンダーはソフトウェアのセキュリティを強化でき、研究者は発見に対して報酬を得られます。このトピックについては、セキュリティ領域において独立した章に値すると考えているため、後ほど詳しく取り上げます。

Jake Archibald氏はGoogleのデベロッパーアドボケートで、複数のブラウザに影響する脆弱性を最近発見しました。彼はその調査過程、各ベンダーへの報告方法、そして各社の反応を興味深いブログ記事にまとめており、一読の価値があります。

開発者のための「ブラウザ」の捉え方

ここまでで、シンプルかつ極めて重要な概念を理解できたはずです。ブラウザとは、一般的なインターネット利用者のために作られたHTTPクライアントにすぎないということです。

プラットフォーム標準のHTTPクライアント(Node.jsのrequire('http')などを想像してください)よりははるかに高機能ですが、結局のところ、より単純なHTTPクライアントの自然な進化形にすぎません。

開発者にとって使い慣れたHTTPクライアントといえば、Daniel Stenberg氏によるcURLでしょう。Web開発者が日々使う最も人気のあるツールの1つです。cURLを使えば、コマンドラインからHTTPリクエストを送り、その場でHTTP通信を実行できます。

$ curl -I localhost:8080

HTTP/1.1 200 OK
server: ecstatic-2.2.1
Content-Type: text/html
etag: "23724049-4096-"2018-07-20T11:20:35.526Z""
last-modified: Fri, 20 Jul 2018 11:20:35 GMT
cache-control: max-age=3600
Date: Fri, 20 Jul 2018 11:21:02 GMT
Connection: keep-alive

この例では、localhost:8080/のドキュメントをリクエストし、ローカルサーバーが正常に応答しました。

ここではレスポンスボディをターミナルに垂れ流す代わりに、-Iフラグを使って「レスポンスヘッダーだけに興味がある」ことをcURLに伝えています。さらに一歩進んで、-v(verbose)オプションを使えば、実際に送信されるリクエストの内容まで含めて詳細を出力でき、HTTP通信の一連の流れをより深く観察できます。

$ curl -I -v localhost:8080
* Rebuilt URL to: localhost:8080/
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> HEAD / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< server: ecstatic-2.2.1
< Content-Type: text/html
< etag: "23724049-4096-"2018-07-20T11:20:35.526Z""
< last-modified: Fri, 20 Jul 2018 11:20:35 GMT
< cache-control: max-age=3600
< Date: Fri, 20 Jul 2018 11:25:55 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact

実は、ほぼ同等の情報は主要ブラウザのDevTools(開発者ツール)でも確認できます。

見てきたように、ブラウザは洗練されたHTTPクライアントでしかありません。確かに膨大な機能(資格情報管理、ブックマーク、履歴など)を備えていますが、本質的には「人間のためのHTTPクライアント」として生まれたものです。これは重要なポイントです。多くの場合、Webアプリケーションのセキュリティ検証にブラウザは不要で、cURLでリクエストを送り、レスポンスを確認するだけで済むのです。

最後に指摘したいのは、「何でもブラウザになり得る」ということです。HTTPプロトコル経由でAPIを利用するモバイルアプリを持っているなら、そのアプリこそがあなたの「ブラウザ」です。自分で構築した高度にカスタマイズされたブラウザであり、自分のAPIが返す特定の形式のHTTPレスポンスしか理解しない、特別なブラウザだと言えます。

次回:HTTPプロトコルの深掘りへ

前述の通り、悪意あるユーザーに最も多くの攻撃ベクトルを提供するのは、HTTP通信レンダリングのフェーズです。このため、このシリーズでもこの2つを中心に扱っていきます。

次回の記事では、HTTPプロトコルをさらに掘り下げ、HTTP通信を安全に保つために私たちが講じるべき対策を探っていきます。

原文はodino.orgにて公開(2018年7月29日)。

  1. Indeedでの仕事探しをスピードアップする9つの実践テクニック

    Indeedで理想の求人を見つけるのは、思っている以上に大変な作業です。Indeedには毎日何百件もの求人が掲載されるため、自分に合った求人を見つけて応募するだけでも一苦労です。 そこで本記事では、Indeedでの仕事探しを効率化するための9つのヒントとコツをご紹介します。 1. プロフェッショナルな履歴書を作成する Indeedでプロフィールを作成したら、まず最初に行うべきは履歴書の作成またはアップロードです。関連する経験やスキルを盛り込んだプロフェッショナルな履歴書を作成することで、採用の可能性が大きく高まります。 履歴書を作成したら、次は公開設定を「公開」にするか「非公開」にするかを決め

  2. 【Chrome for Android】新規タブページのおすすめ記事を非表示にする方法

    Facebookが友人がシェアした記事の横におすすめリンクを表示し始めてから、早くも4年が経ちました。他のSNSはあまり同じ路線を追随していませんでしたが、最新版のChrome for Androidでは、新規タブページにおすすめ記事が表示されるようになっています。この変更に不満を感じているユーザーは少なくありませんが、実はこれを無効化する方法があるのです。 ブックマークと最近使ったタブが置き換えられた おすすめ記事の表示によって、従来の新規タブページにあったブックマークや最近使ったタブの表示が失われてしまいました。これらを取り戻すには、Chromeの隠しメニュー(フラグ設定)を2つ操作する必