06/4/2018, 1:09 AM GMT+9

Webサービス製作で引っかかりやすい「同一生成元ポリシー(SOP)」について

同一生成元ポリシー(Same Origin Policy: SOP)は Web セキュリティを考える上で基本的な考え方です。外部APIを利用するWeb サービスにとっては避けては通れない話です。加えて、最近ではSPAの台頭により自前のAPIをclientから叩かせるケースが増加していると思いますが、その場合でも意識しなければならないことがあります。 ちなみに、「生成元」は少し奇妙に聞こえるので、「オリジン」と呼び、「同一オリジンポリシー」と呼ぶ場合もあるそうです。

目的と概要

何のために SOP が必要なのでしょうか。

簡単な Web ページでは、ブラウザはサーバーからデータ(HTML ファイル)を取得しそれをレンダリングします。一度取得したらそれっきりです。何か追加で定期的にデータを取りに行ったりすることはありません。ボタンを押せば画面遷移はしますが、それは新しくページを取りに行っているだけです。

しかし、近年(というほど最近ではないかもしれませんが)、JavaScript などを利用して追加でデータを取得するような仕組みを採用する Web ページが増えています。SPA はその最たる例です。

超快適な操作感の Web アプリを実現する技術: SPA(Single Page Application)について調べてみた

このような目的で行われるアクセスは、もとのページとサーバーが同じ(後述しますが正確には同一オリジン)です。ブラウザもこれについては特に制限しません。

では、異なるサーバーへのアクセス(クロスオリジン(後述))だったらどうでしょう。ここで問題なのは、アクセスするのはサーバーからではなくブラウザからだということです。(「Web サイトが・・・を取得する」という表現はその Web サイトのサーバーがデータを取得するという意味で用いられることも在るかもしれませんが、この場合の Web サイトはまさに Web サイト(の JavaScript など)がデータを取得しに行くという意味です)

つまり、Twitter にアクセスするのならユーザーが普段見るようなログイン済みの Twitter の画面を取得できてしまうことです。(サーバーからのアクセスなら問題のない話です。ユーザーが ID とパスワードを渡さなければよいからです。逆に、ブラウザが取得するなら問題ないだろうと考える人もいるかも知れません。しかし、取得したデータを JavaScript を用いて元のサーバーに送ることは可能なはずです。)

ブラウザとしてはこれを認めるわけには行きませんので、ブロックします。

SOP は JavaScript などから異なるオリジンへの干渉をブラウザレベルで防ぐことでユーザにとってのセキュリティを担保するための仕組みなのです。

オリジンの定義

以下の 3 つがすべて一致する組を同一とみなす。

  • ホスト(FQDN)
  • スキーム(http とか https も区別される)
  • ポート

ですから、以下のいかなる組み合わせも異なるオリジンとみなされます。

  • http://support.cosnomi.com/
  • http://blog.cosnomi.com/
  • https://support.cosnomi.com/
  • http://support.cosnomi.com:8080/

以下のいかなる組み合わせも同一オリジンです。

  • https://support.cosnomi.com/
  • https://support.cosnomi.com/maintenance/
  • https://support.cosnomi.com:80/

繰り返しになりますが、アクセス元とアクセス先が同一オリジンならブラウザはブロックしません。同一オリジンでないなら、ブラウザはそのアクセスに制限をかけることになります。その制限について見ていきましょう。

何が出来て何が出来ないか

異なるオリジンから来たデータについてブラウザはどのような制限を行うのでしょうか。

  1. XMLHttpRequest
  2. iframe や Window
  3. Canvas

他にも様々な制限がありますが、この 3 つ、特に XMLHttpRequest を重点的に説明します。

XMLHttpRequest(XHR)はサーバーから非同期に(受信済みの web からさらにリクエストできる)データを取得するための仕組みで、Ajax などで重要な技術です。前述のような JavaScript によるアクセスというのは XHR を利用しています。同一オリジンに対しては、XHR を用いてデータを取得できますが、異なるオリジンへのアクセス(クロスオリジン)は許可された場合を除き、ブラウザによってブロックされます。これによって、前述のような不正なデータ取得を防止します。

また、iframe や window に対する操作の制限も行われます。要するに埋め込まれたコンテンツの中身は、埋め込んでいる Web サイトからは取得できないということです。

Canvas も iframe などと同様に一部の操作が制限されます。

回避策

とはいえ、これでは不便な場合もあります。

例えば、https://example.com/ から送信されるJavaScriptから https://api.example.com/news にアクセスしてデータを取ってきて表示したい場合、これらの2つは異なるオリジンですので、アクセスは制限されてしまいます。これが、自前のAPIを利用する場合でもSOPに引っかかるというケースです。いくらサーバー側でどうにかしようと思っても SOP はブラウザ側でのブロックですので通常はどうすることもできません。

しかし、これは非常に不自由です。そもそも問題なのは、アクセス元のスクリプトが悪意を持って、アクセス先にあるクライアントに関する情報を取得しようとしていることです。つまり、アクセス先のサイトがアクセス元を信頼しているということがブラウザに伝われば、ブラウザはこのような制限を掛ける必要はないわけです。この信頼関係をブラウザに伝える方法として、CORS という技術があります。詳しくは、CORSについて説明した記事をご覧ください。

まとめ

  • 同一生成元ポリシーはクロスオリジンでのアクセスを制限する考え方
  • オリジンは「ホスト」「スキーム」「ポート」の組
  • JavaScript をりようした XMLHttpRequest も制限の対象
  • 回避するには CORS など

Cosnomi
Cosnomi

コンピュータ(Web, 機械学習など)が好きな医学部生

Twitter / GitHub