[Web セキュリティ] SOP(Same-Origin Policy) について理解する
[Web セキュリティ] SOP(Same-Origin Policy) について理解する
参考になりそうな人
・新卒未経験エンジニアの方
・Web セキュリティについて初学者の方
・SOP とは何かを知りたい方
・SOP を理解すると何がいいのか知りたい方
はじめに
自己紹介
こんにちは。
株式会社 Sun Asterisk に所属する naonaonaoki といいます。
23 卒エンジニア職として入社し、現在は研修が終わり OJT としてプロジェクトに join しています。
背景
なぜこの記事を書こうと思ったかというと、すごくシンプルかつありふれたものになるのですが、
"自分自身が研修期間中に苦労した経験があり、そこで学んだことをアウトプットしつつ、同じように困っている人がいたら少しでも助けになればいいなと思ったから"
という理由になります。
私自身、大学時代にプログラミングは軽くやったことあるが実務は未経験という人で、特に Web セキュリティに関しては全くの無知の状態でした。
そんな中、研修中に個人開発をする課題があったのですが、SOP についての理解がないためにエラーが解決できず、その後同期や先輩の教えのもとエラーは解決できたが本質的なところが自分の中で理解できていないような気がしてすごくモヤモヤするということがありました。
そこで参考にも記載している『Web ブラウザセキュリティ―Web アプリケーションの安全性を支える仕組みを整理する』という本を読み、「なるほど」とすごく納得できたので、ここで学んだことをアウトプットしてより定着させつつ、同じように困っている人がいたら少しでも助けになればいいなと思い、今回の記事を書こうと思いました。
(ちなみに、上記の本は Web セキュリティについて体系的に学ぶことができる良書なので、一度手にとって見て学習してみるのも良いかもしれません。)
ここから本編
前提確認:Origin とは?
SOP の説明に入る前に、SOP を説明する上で欠かせない Origin(オリジン)について説明します。
一般的に Origin とは、「(スキーム、ホスト名、ポート番号)の 3 つの組のことである」として定義されています。
ただし、厳密には必ず上記の定義になるというわけでもないようです。
例えば、以下の 3 つがあります。
- http:あるいは https:スキームの各 URL に対する Origin は、(スキーム, ホスト名, ポート番号)の 3 つ組として定義される値です。
- RFC 6454 では、原則として ( スキーム, ホスト名, ポート番号 ) を Origin として定義していますが、URI にオーソリティ部分(host.example.com など)が存在しない場合などには、適当に生成されたユニークな識別子が Origin とされています。
- HTML Standard [WHAb]においては、任意の Document オブジェクト、img オブジェクト、audio オブジェクト、video オブジェクトに対する Origin の定義が与えられています。こちらでは、document.domain(後述)のことを考慮して、(スキーム, ホスト名, ポート番号, ドメイン)からなる 4 つの値の組(tuple origin)、あるいは何らかの内部的な値(opaque origin)のどちらかとして Origin が定義されています。
これらを踏まえて 3 つほど例を紹介します。
-
(例 1):http://naonao0.example.com に対する Origin
- この例は、スキームが http であり、ホスト名は naonao0.example.com です。
URL 中ではポート番号が省略されていますが、HTTP のデフォルトのポート番号は 80 番なので、最終的に Origin は (http, naonao0.example.com, 80) となります。
- この例は、スキームが http であり、ホスト名は naonao0.example.com です。
-
(例 2):https://naonao1.example.com/show に対する Origin
- この例は、先の例とは違い、URL にパス(/show)が含まれています。
しかし、Origin にパスは関係ありません。HTTPS のデフォルトのポート番号は 443 ですから、この URL に対応する Origin は(https, naonao1.example.com, 443)となります。
- この例は、先の例とは違い、URL にパス(/show)が含まれています。
-
(例 3):http://naonao2.example.com:8080/show に対する Origin
- この例ではポート番号が明記されているので、Origin のポート番号部分は 8080 となります。
この URL に対応する Origin は (http, naonao2.example.com, 8080)です。
- この例ではポート番号が明記されているので、Origin のポート番号部分は 8080 となります。
SOP とはなにか?
「ある 2 つの Web リソースの Origin が一致しているとき、それらは Same-Originである」といいます。
一方、「2 つの Web リソースの Origin が異なるときは Cross-Origin である」といいます。
そして、「Cross-Origin なリソースへのブラウザ内アクセス[1]の禁止と、Cross-Origin なリソースへのネットワーク越しのアクセス[2]の部分的な禁止」を行うセキュリティ機構のことを SOP(Same-Origin Policy)といいます。
図にするとこんな感じです。
あるサイトでWebサーバーAとWebサーバーBのリソースを同時に掲載する場合のイメージ[3]
ちなみに、SOP のもとでのリソース間の操作に対する制限を表にするとこんな感じです。
SOP のもとでのリソース間の操作に対する制限[4]
SOP の私なりのイメージ
少し難しいと思った方は、住居をイメージするともう少し理解が進むかもしれません。
想像してみてください、あなたは住んでいるアパートの一室にいます。
このアパートには複数の部屋がありますが、各部屋はドアで仕切られていて、他の部屋に直接アクセスすることはできません。
各部屋は他の人が住んでおり、彼らは自分の部屋でプライバシーを保ちつつ生活しています。
(もし勝手に他の人が自分の部屋に入ってきたらビックリするし大事ですよね。)
このアパートを Web の世界に当てはめると、各部屋は異なる Origin を表しています。
Origin には、( スキーム, ホスト名, ポート番号 ) が含まれます。
SOP は、異なる Origin の間でのデータ共有を制限するため、各 Origin は自身の「部屋」内でデータを保護することができます。
おわりに
今回は SOP について理解するというタイトルのもと書いてきました。
学んだことをまとめます。
- Origin とは、一般的に「(スキーム、ホスト名、ポート番号)の 3 つの組のことである」。
- SOP とは、「Cross-Origin なリソースへのブラウザ内アクセスの禁止と、Cross-Origin なリソースへのネットワーク越しのアクセスの部分的な禁止」を行うセキュリティ機構のこと。
このように、SOP は Web 上でのデータのセキュリティを強化する仕組みであり、不正なデータの取得や悪意のある攻撃を防ぐ役割を果たしています。
ただし、残念ながら"SOP を学べば Web セキュリティはすべて解決!"というわけではありません。
SOP について理解した後は、CORS(Cross-Origin Resource Sharing) や SOP の天敵である XSS(Cross Site Scripting) などについて理解する必要があります。
CORSやXSSなどに関しては、私自身Webセキュリティについての理解を深めた上で、別途記事にできればと考えています。
(『Web ブラウザセキュリティ―Web アプリケーションの安全性を支える仕組みを整理する』を一度読んでみるのも良いと思います。)
この記事を読んでいただいた方の助けに少しでもなれていれば幸いです。
また、私自身、OJT など含め今後とも頑張っていこうと思いますので、よろしくお願いいたします。
最後まで読んでいただき、ありがとうございました!
-
ブラウザ内アクセス:Fetch API などにより取得したリソースの中身の操作や、ウィンドウへの参照を経由した DOM の操作など。 ↩︎
-
ネットワーク越しのアクセス:
<a>
タグや<form>
タグによるページ遷移や、Fetch API による HTTP リクエストの発行など。 ↩︎ -
米内貴志(2021) . 『Web ブラウザセキュリティ―Web アプリケーションの安全性を支える仕組みを整理する』 . ラムダノート株式会社 , p30 より引用 ↩︎
-
米内貴志(2021) . 『Web ブラウザセキュリティ―Web アプリケーションの安全性を支える仕組みを整理する』 . ラムダノート株式会社 , p31 より引用 ↩︎
-
単純リクエストの発行:、
<a>
タグや<form>
タグによって自然に発生するような HTTP リクエスト ↩︎ -
埋め込み:
<iframe>
タグや<img>
タグなどによるページ中へのリソース埋め込みなど ↩︎
Discussion