Slide 1

Slide 1 text

クロスオリジンの話 unarist

Slide 2

Slide 2 text

微妙にふわっとしたタイトルやな…

Slide 3

Slide 3 text

今日話すこと ● オリジンとかクロスオリジンとかなんやねん ● 同一オリジンポリシーやCORSの話 ● 発展的トピック 以下には重点を置いていません。 ● Webアプリの脆弱性の網羅的な説明 → 徳丸本を読みましょう ● 最近流行りの攻撃 → OWASPとか徳丸チャンネルを見ましょう

Slide 4

Slide 4 text

今日覚えて帰ってほしいこと ● ありません!!! ● バスツアーぐらいの感じでお楽しみください。

Slide 5

Slide 5 text

Q. 以下の言葉知ってますか? ● オリジン ● クロスオリジン ● 同一オリジンポリシー / Same-Origin Policy ● CORS / Cross-Origin Resource Sharing

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Origin = scheme + hostname + port の組 例: http://example.com:8080/~username/index.html

Slide 8

Slide 8 text

リクエスト元・先のOriginが等しい → Same-Origin / 同一オリジン

Slide 9

Slide 9 text

リクエスト元・先のOriginが等しい → Same-Origin / 同一オリジン さまざまな操作を同一オリジン間に制限する仕組み → Same-Origin Policy / 同一オリジンポリシー

Slide 10

Slide 10 text

リクエスト元・先のOriginが異なる → Cross-Origin / クロスオリジン

Slide 11

Slide 11 text

リクエスト元・先のOriginが異なる → Cross-Origin / クロスオリジン 同一オリジンポリシーの制限を緩和する仕組み → CORS (Cross-Origin Resouce Sharing), etc.

Slide 12

Slide 12 text

同一オリジンポリシーとCORS ● Webの世界は昔からオリジン境界で色々守ってきた ● オリジンを越えて許されていたことの例: ○ リンクなどによるページ遷移 ○ フォーム送信 ○ リソース埋め込み(img/script/video/etc.) ■ よくできているので、埋め込まれたimgをcanvasに描画してそれを持ち出す、とかもで きない(taint=汚染)される

Slide 13

Slide 13 text

Web園児猫「もうちょっと色々したいんじゃ…!」

Slide 14

Slide 14 text

同一オリジンポリシーとCORS ● (多分)JS芸とかが広がってきて、ブラウザ内でインタラクティブにやるの が流行ってきた ○ (Ajaxとか)(GoogleMapとか話題になったよね) ● 同一オリジンはXMLHttpRequestさえあれば簡単 ● クロスオリジンは……は…… ○ 古のハック、JSONP…… ○ scriptタグで埋め込んでJSONを受け取れる。 var script = document.createElement(“script”); script.src = “http://example.com/api/jsonp?callback=hoge document.body.appendChild(script); function hoge(resp) { console.log(resp); }

Slide 15

Slide 15 text

CORS「待たせたな!!」

Slide 16

Slide 16 text

CORS (Cross-Origin Request Sharing) ● これまで同一オリジンポリシーで制限されていたリクエストを、サーバー側 の明示的な許可のもと制限を緩和する仕組み ● サーバー側の明示的な許可 = Access-Control-ほげほげ HTTP/1.1 200 OK Content-Length: 0 Connection: keep-alive Access-Control-Allow-Origin: https://foo.bar.org Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: X-Foo, X-Bar Access-Control-Max-Age: 86400

Slide 17

Slide 17 text

CORS (Cross-Origin Request Sharing) 肝心なのは「同一オリジンポリシーを緩和するもの」ということ。 いままでできたことは変わらずできる ○ リンクでの遷移、フォーム送信、リソース埋め込み: できる ○ これらと同等のリクエスト: できる (単純リクエスト) できなかったことは許可されればできる ○ 単純リクエストのレスポンスをJSで読み取る: 読み取り前にCORSでの許可が必要 ■ リクエストはできるが、レスポンスにCORSヘッダがないと読み取れない ○ メソッドやヘッダーを自由に設定したリクエスト: リクエスト前にCORSでの許可が必要 ■ リクエスト前にプリフライトリクエストが飛ぶ

Slide 18

Slide 18 text

プリフライトリクエスト 許可がないとリクエストしていいかもわからない時に、先にお伺いを立てる。 OPTIONS /doc HTTP/1.1 Host: bar.other Connection: keep-alive Origin: https://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type HTTP/1.1 204 No Content Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin 👦こういうリクエスト投げたいっす! 👨この条件ならええやで。

Slide 19

Slide 19 text

ところで Failed to fetch という 言葉に聞き覚えは?

Slide 20

Slide 20 text

忌しき Failed to fetch

Slide 21

Slide 21 text

忌しき Failed to fetch CORSで許可されていない場合、リクエスト結果はJSに対して開示できない ○ 成功時のレスポンス、失敗時のレスポンス、リクエストに失敗した理由、etc. ○ 全てをオブラートに包んだエラー「Failed to fetch」 ○ 開発者ツールでコンソールを確認するとかしないと、なんもわからん CORS設定しているはずなのに出るんだけど……🤔 ○ 例えばエラーレスポンスにCORSヘッダがないと、やっぱり Failed to fetch 行き ○ 忘れがちなケースとして、リバースプロキシやWAFが弾いているとか……

Slide 22

Slide 22 text

CORSとの付き合い方

Slide 23

Slide 23 text

レスポンスヘッダーにあれこれ詰める ○ 最低限必要なのは Access-Control-Allow-Origin ○ シンプルリクエストに該当しないメソッドやリクエストヘッダーを使う場合、 プリフライト リクエストに対応しつつ、Access-Control-Allow-Methods や Access-Control-Allow-Headers も返す ○ CookieやBASIC認証とかも送ってほしい場合は Access-Control-Allow-Credentials ■ この場合 Access-Control-Allow-Origin 等でワイルドカードは使えない ○ 追加でレスポンスヘッダを公開したい時は Access-Control-Expose-Headers リクエスト側はそんなにオプションいらない ○ fetch() でいうと { mode: “cors” } というオプションがあるが、これがデフォルト ○ 資格情報を送る場合は { credentials: “include” } 等が必要 CORSの設定

Slide 24

Slide 24 text

同一オリジンポリシーで防げないものは防げない 単純リクエストで副作用が起きるケース ○ 「ぼくははまちちゃん! こんにちはこんにちは!!」 ○ 📰https://www.itmedia.co.jp/enterprise/articles/0504/23/news005.html ○ いわゆる CSRF/XSRF (Cross-Site Request Forgeries) ■ fetchでも { mode: "no-cors", credentials: "include" } とかでやれるぞ ○ 対策: CSRFトークンをつける、単純リクエストにしない、後述の SameSite 属性、etc. ○ もちろん、GETリクエストで副作用を起こしたりしてないですよね? 埋めこまれるのも困るケース ○ 現実的な具体例が浮かばないが…… ○ 対策としては Cross-Origin-Resource-Policy ヘッダとか……?

Slide 25

Slide 25 text

CORSで解決

Slide 26

Slide 26 text

なにこれ

Slide 27

Slide 27 text

ネットワーク通信以外のクロスオリジン ブラウザのタブ間・ウィンドウ間で通信できるもの ○ postMessage API ■ 送り手・受け手どちらもoriginをチェックしような! ○ window.open / window.parent / iframe.contentWindow / etc. ■ windowオブジェクトが触れたり触れなかったりする ストレージ系 ○ Cookie: サイト単位の管理 ■ サブドメインがまとめられたり、オリジンとはまた違う単位… ○ IndexedDB / WebStorage / etc.: オリジン単位の管理 ■ 📰最近別オリジンのIndexedDBがチラ見えするバグがWebKitで話題でしたね? ■ GoogleのユーザーIDとかが見えるので、特にプライバシー観点でまずい

Slide 28

Slide 28 text

ネットワーク通信以外のクロスオリジン この辺は既に緩めだったので、制限を厳しくするオプションが生えがち ○ Cross-Origin-Opener-Policy / Cross-Origin-Embedder-Policy / iframe sandbox ○ Spectre👻騒動で一部APIにこれらが必須になったりした 場合によってはデフォルト・強制で制限を厳しくされたりもしている ○ Cookie: SameSite属性, 3rd-party Cookie の制限, ITP ○ 📰SameSite=Lax はChromeやFirefoxがデフォルトにして話題になっている ■ SameSite=None をつけないとCORSが設定されていてもCookieが送られなくなる ○ Cookieに関してはプライバシー観点の話題が絶えないのもある

Slide 29

Slide 29 text

おまけ: CSP (Content-Security-Policy) クロスオリジンに限らず、Webページで扱うリソースに制限をかける仕組み ○ 主に XSS (Cross-Site Scripting) の被害を低減したり報告するのに使われる ○ img / script / style / (i)frame など、様々なリソースの出所を制限することができる ○ つまり、XSS で変なリソースを読み込まされそうになっても、ブロックできる! ○ ベタ書きされた style や script もブロックできる! ○ (ブラウザにもよるが、UserScript / UserStyle もブロックされたりする) # 現在のオリジンからの取得とインライン指定のみ許可。他所やevalは禁止。 Content-Security-Policy: default-src self ‘unsafe-inline’ # https スキームのみを許可 Content-Security-Policy: default-src https:

Slide 30

Slide 30 text

おしまい