質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • JavaScript

    17499questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSONP

    31questions

    JSONP(JSON with padding)は、JSONを使用した関数呼び出しのための仕組み。クロスドメインでのデータの受け渡しが可能です。JavaScriptからクロスドメインで容易にデータを扱うことができます。

JSONP利用時のCSRF対策

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 812

aiueo123

score 9

前提・実現したいこと

CSRFの仕組みを理解し、JSONPを利用するときにセキュリティ対策する

発生している問題・エラーメッセージ

CSRFの仕組みが分からない。
下記2番の「アクセスできる」、というのはログインしたからだと理解できるが、
そのあとの「取得する」という行為が何故できるのかわからない。
スクリプト例などを載せて具体的に仕組みを教えて頂ければ幸いです。

該当のソースコード

1.サイトAにログイン済みの被害者が攻撃者の用意した悪意あるスクリプト(スクリプトBとする)が埋め込まれたWebページにアクセスする。
2.スクリプトBはJavaScriptから機密情報を保持したサービスA(JSONP)にアクセスして、これを取得する。1で被害者はサイトAにログイン済みのため、サービスAには問題なくアクセスできる。←被害者は意図せずサービスAにアクセスしてしまう=CSRF脆弱性!
3.スクリプトBはサービスAから取得した機密情報を攻撃者のサイトに(XmlHttpRequest等を使って)送る。←機密情報の漏えい!!
(引用元:https://www.ark-web.jp/blog/archives/2007/01/web20jsonp.html)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

ヘソクリの在処と金額を管理しているサービス H が https://hesokuri.example.com/ で展開されているとしましょう。これとは別に統合資産管理サービス S が https://shisan.example.com/ で展開されています。サービス H はヘソクリ情報にアクセスできる API を JSONP で提供しており、サービス S もこの API を利用し、ヘソクリ以外の資産も含めて統合的に管理できる機能をユーザに提供しています。

A さんは、サービス H とサービス S を両方利用しています。

  1. A さんがサービス H にログインし、資産管理ページ、https://shisan.example.com/kanri にアクセスしたとします。
  2. ここでサイト H は https://hesokuri.example.com/checkUserStatus?site=shisan にリダイレクトするよう A さんのブラウザに返します。
  3. するとブラウザからサイト H にリクエストが飛びます。
  4. サイト H では、checkUserStatus が呼ばれたら、クエリストリングの site が事前に登録されているものかチェックします。shisan は正規の提携先として登録されているのでよしとします。
  5. 次にリクエストしてきたユーザがログイン済みかをチェックします。ログイン済みでないならログイン画面を出し、ログインさせます。あと、サービス S がサービス H 内の A さんのヘソクリ情報にアクセスするのを許可するかどうかを聞く画面を出します。ここでは、A さんがログイン状態になり、サービス S にヘソクリ情報を使ってもいいと許可したことにします。
  6. サイト H は、A さんが「許可」ボタンを押した後のページとして、HTML を返さず、代わりに https://shisan.example.com/accepted/ にリダイレクトするよう指示を出します。この元のサービスに戻る URL は、最初の site=shisan に紐付くデータとして、サイト H のデータベースに格納されています。
  7. ブラウザは https://shisan.example.comn/accepted にリダイレクトします。
  8. サイト S では、資産管理画面を出します。この画面の html 中に、<script src="https://hesokuri.example.com/getHesokuriInfo.js?callback=listHesokuriInfo" /> というタグが含まれています。
  9. A さんのブラウザがこの html をレンダリングしようとすると、https://hesokuri.example.com/getHesokuriInfo.js?callback=listHesokuriInfo へのアクセスが発生します。このリクエストには、ログイン認証済みの証しが cookie に載って飛びます。(JSONP 呼び出し)
  10. サイト H は、cookie の情報に基づき、A さんのヘソクリ情報をデータベースから取得し、listHesokuriInfo([{ place: "冷凍庫の製氷機の下", amount: 150000}]); を返します。A さんは製氷機の下に 15 万円隠しているようです。もちろん、この関数名は、JSONP 呼び出しのときの callback パラメータで渡ってきた値を利用しています。
  11. ブラウザでは返ってきた JavaScript を評価するわけですが、listHesokuriInfo([{ place: '冷凍庫の製氷機の下', amount: 150000}]); なので、この関数の実行となります。これは 8. で返ってきた html の中で、JSONP 呼び出しより前に定義されている関数です。サイト S の資産管理画面の該当部分にやってきたデータをはめこんだりします。

まあ、これが JSONP で API を提供しているサイト H と、それを利用したサービスを展開するサイト S の連携です。

で、これを悪用するのがサイト N https://nusutto.example.com/ です。

  • A さんがログイン状態で https://nusutto.example.com/ を踏んでしまったとしましょう。
  • サイト N では画面を html で返しますが、この html 中に、<script src="https://hesokuri.example.com/getHesokuriInfo.js?callback=sendHesokuriInfo" /> というタグが含まれています。
  • A さんのブラウザがこの html をレンダリングしようとすると、https://hesokuri.example.com/getHesokuriInfo.js?callback=send へのアクセスが発生します。このリクエストには、ログイン認証済みの証しが cookie に載って飛びます。(JSONP 呼び出し)
  • サイト H は、cookie の情報に基づき、A さんのヘソクリ情報をデータベースから取得し、sendHesokuriInfo([{ place: "冷凍庫の製氷機の下", amount: 150000}]); を返します。(CSRF 成功)
  • ブラウザでは返ってきた JavaScript を評価するわけですが、sendHesokuriInfo([{ place: '冷凍庫の製氷機の下', amount: 150000}]); なので、この関数の実行となります。サイト N が用意しているこの関数は、盗んだヘソクリ情報をあれこれ悪用します。

CSRF 攻撃は、ブラウザからのアクセスからは正規のものと非正規のものとが区別できない、ということから可能になってしまいます。CSRF 対策は、けっきょく、正規の一連の流れの中におけるリクエストなのか、を判断するしかありません。一般には、CSRF 対策が必要なページに先立つページでトークンを発行し、WEB アプリ側のセッションに格納しておきます。CSRF 対策が必要なページでトークンがリクエストに乗る仕組みにしておき、リクエストが来たときにそこに乗っているトークンとセッションに格納したトークンが一致すれば正規のリクエストとすることで、CSRF を防ぐことができます。
JSONP はそもそもそういう流れがないクロスドメイン API ですが、先立ってトークンを用意しておいて、あとでリクエスト時に渡されるトークンとの一致で見るしかないかと思います。やりかたはいろいろあると思いますが、たとえば、先の正規の流れの 6. のところでサイト H が返すリダイレクト先を https://shisan.example.com/accepted/?token=x2032 とすることかと思います。トークンの実際の値は 5. の段階で発行し、セッションにも格納しておきます。で、サイト S が 8. で JSONP を呼び出す際、このトークンを利用し、<script src="https://hesokuri.example.com/getHesokuriInfo.js?callback=listHesokuriInfo&token=x2032" /> というタグを生成する、と。

かなり適当に書いたので穴はあるかもしれませんが、どうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/06 21:01

    ご回答ありがとうございます。
    おかげさまで、一連の流れが理解できました。
    CSRF対策の説明文で出てくる「トークン」とはなんですか?
    googleで調べたのですが、解説サイトによって意味がまちまちでした。

    キャンセル

  • 2017/09/06 21:11

    トークンは文脈によっていろいろな意味がありますので。「トークン」だけでググっても混乱するだけかもしれません。CSRF 対策では、チェックすべきリクエストに乗ってくる秘密の文字列のことで、これがセッション中に格納してあるものと同じかどうかで正しいリクエストか判定するものです。CSRF は、本来の「正しい」フローではないリクエストが成立してしまうことが問題なわけです。チェックすべきリクエストの前のリクエストで秘密の文字列、すなわちトークンをサーバで生成し、それをセッションに格納するとともにクライアントに返します。クライアントが正規のトークンを送ってきた、ということは、その前に「正しい」リクエストを経たことがわかります。

    キャンセル

  • 2017/09/06 21:25

    分かりました。丁寧な解説有難うございます。

    キャンセル

  • 2017/09/06 23:18

    通常の WEB アプリでは、Cross Site な Request を防げばいいわけですが、JSONP は Cross Site な
    Request が正常なリクエストですから、Cross-Site Request Forgeries (CSRF) を防ぐのは本質的に難しいですよね。

    キャンセル

+2

JSONPは、もともとクロスドメインを突破するために編み出された技術です。

XMLHttpRequestがクロスドメインでの通信に対応していなかった頃にも、<script>タグはドメインを問わず使えたので、「これを使って通信してしまおう」と考えた人がいました。

callback({"foo": "bar" /* さらにJSONデータが続く */});

JSONPのリクエストをかけると、上のようなレスポンスが返ってきます。<script>タグでこれを読み取れば、callback関数が、JSONデータを引数として実行されることで、データを伝える、という流れです。

<script>要素は昔からあったこともあって、CSPなどで意図的に設定しない限り、どこのドメインのでもアクセス可能なのです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/06 20:44

    ご回答ありがとうございます

    キャンセル

同じタグがついた質問を見る

  • JavaScript

    17499questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • JSONP

    31questions

    JSONP(JSON with padding)は、JSONを使用した関数呼び出しのための仕組み。クロスドメインでのデータの受け渡しが可能です。JavaScriptからクロスドメインで容易にデータを扱うことができます。