パスワードを忘れた? アカウント作成
この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。

正しいCSRF対策、してますか?」記事へのコメント

  • by tix (7637) on 2006年04月02日 18時54分 (#913853) ホームページ
    金床氏の提案する対策(「正しい対策その1: ワンタイムトークンを正しく使用する方法」)は、主に次の二つから成ります。リクエスト1とかレスポンス1とかの意味は金床さんのページ [jumperz.net]を参照してください。
    1. リクエスト1を POST にする(リクエスト1がGETだったらサーバーはエラー等を返すようにする)
    2. ワンタイムトークンを使用する。詳しくは、 (a) 処理1でワンタイムトークンを生成する。 (b) レスポンス1に含まれるフォームにトークンを hidden フィールドとして追加する。 (c) 処理2では本来の処理(日記にデータを追加する等)の前に、 cookie として送られてきたセッション ID と hidden フィールドとして送られてきたトークンの組み合わせが正当であることを確認する
    1は CSSXSS 脆弱性の悪用を防ぐために必要です。金床氏自身も
    まず、アプリケーションの作りとして、リクエスト1が必ずPOSTを用いるような形にする。これによってCSSXSS脆弱性を利用したhiddenフィールドの情報の抜き取りを防ぐことができる。
    と書いています。しかし、2はどうして必要なのか、金床氏は説明していないように思いました。少なくとも僕には理解できませんでした。

    高木氏は、
    • (a) レスポンス1に含まれるフォームにセッション ID を hidden フィールドとして追加する。 (b) 処理2では本来の処理の前に、クッキーとして送られてきたセッション ID と hidden フィールドとして送られてきたセッション ID が一致してかつ正当であることを確認する
    ということを提案しました。このままでは、(「リクエスト1の方法によっては」という留保が必要だと思いますが) CSSXSS 問題のせいで危険である、というのが金床氏のページの要点だと思います。であれば、高木氏の提案する対策に加えてさらにリクエスト1を POST 専用にすれば、今問題になっている CSRF 攻撃対策と CSSXSS 問題対策はできているように思います。僕は何か見落としているんでしょうか。

    (efさんのコメント [srad.jp]に POST であっても CSSXSS 問題が悪用できる場合があると書かれていて、それを僕は理解できていないので、何か見落としがあるとしたらその辺りではないかと睨んでいますが……。)
    --
    鵜呑みにしてみる?
    • by Anonymous Coward on 2006年04月03日 2時07分 (#914010)
      > であれば、高木氏の提案する対策に加えてさらにリクエスト1を POST 専用にすれば、今問題になっている CSRF 攻撃対策と CSSXSS 問題対策はできているように思います。僕は何か見落としているんでしょうか。

      それで、CSRF と CSSXSS は防げます。
      ただし、対策を行わなかった場合には、Cookieに保存されている
      セッションIDはCookie以外には保存されることはありません。
      しかし、貴方の言うセキュリティ対策を行うと、
      HTML内のhiddenフィールドにセッションIDが埋め込まれることになるわけです。

      これが万が一漏洩したらセッションハイジャックの危険があります。
      (他のブラウザのセキュリティホールやプロキシサーバのキャッシュ、PCの共有などが無ければ問題ありませんがね。)

      冷静に考えてみて下さい。
      SCRF対策、CSSXSS対策を行ったことにより、
      他のセキュリティホールが生じる可能性が高まる状況は好ましいと言えますか?

      親コメント
      • >しかし、貴方の言うセキュリティ対策を行うと、
        >HTML内のhiddenフィールドにセッションIDが埋め込まれることになるわけです。
        >(他のブラウザのセキュリティホールやプロキシサーバのキャッシュ、PCの共有などが無ければ問題ありませんがね。)

        他の脆弱性?それを言うなら、クッキーにセッションIDを入れる方がよっぽど危ないですから、hiddenにセッションIDを入れるべきです。

        「hiddenは漏れるがクッキーは漏れない」なんて脆弱性、CSSXSS以外に聞いたことがありませんし。
        • Cookieを使わずにPOSTメソッドのhiddenでセッション管理をしている会員制のWebサイトであれば、CSRF及びCSSXSSの影響は受けません。

          金床氏の提案する「正しい対策その1: ワンタイムトークンを正しく使用する方法」もCookieでセッション管理することを前提で書かれていました。

          「セッションIDをCookieに入れる」のと「セッションIDをCookie及びhiddenに入れる」のでは、 後者の方がセキュリティ上のリスクは高いのでは無いでしょうか。

          親コメント
          • 「セッションIDをCookieに入れる」のと「セッションIDをCookie及びhiddenに入れる」のでは、後者の方がセキュリティ上のリスクは高いのでは無いでしょうか。
            前提は何ですか?
            クライアント側に脆弱性がないなら、リスクは同じでしょう。
            • 前提条件が抜けていました。
              大変失礼しました。

              前提は、ブラウザの脆弱性、プロキシのキャッシュ、第三者のコンピュータの利用なども考えられる、現実社会の環境です。
              親コメント
              • 前提は、ブラウザの脆弱性、プロキシのキャッシュ、第三者のコンピュータの利用なども考えられる、現実社会の環境です。
                そのようなもののすべてを前提とするなら、どうやっても危険なので、リスクは同一ですね。(∞=∞)
      • (他のブラウザのセキュリティホールやプロキシサーバのキャッシュ、PCの共有などが無ければ問題ありませんがね。)
        プロキシサーバのキャッシュにはSet-Cookieも残りますよ。
        PCの共有でCookieが漏れないとでも?
        • >プロキシサーバのキャッシュにはSet-Cookieも残ります
          LANでシビアな情報をやり取りするのは、パケット傍受される危険性があるよレベルの話。
          ここでいうCSRF対策とは既に別次元の話だから、そういう可能性(他のブラウザ以下)
          は考慮しないで済むので問題ありません、という事では?

          話題がセキュリティ一般であるなら、考慮しないでよい理由は無いだろうけど。
          • しかし、貴方の言うセキュリティ対策を行うと、 HTML内のhiddenフィールドにセッションIDが埋め込まれることになるわけです。
            これが万が一漏洩したらセッションハイジャックの危険があります。 (他のブラウザのセキュリティホールやプロキシサーバのキャッシュ、PCの共有などが無ければ問題ありませんがね。)
            プロキシサーバのキャッシュにはSet-Cookieも残りますよ。
            LANでシビアな情報をやり取りするのは、パケット傍受される危険性があるよレベルの話。ここでいうCSRF対策とは既に別次元の話だから、そういう可能性(他のブラウザ以下) は考慮しないで済むので問題ありません、という事では?
            話がかみ合っていませんね。
            「Cookieは漏洩しないがhiddenフィールドは漏れる」という想定が間違いという話でしょう。
      • >それで、CSRF と CSSXSS は防げます。
        そうすると金床氏の「高木方式ではCSRF対策になっていない」という主張は間違いですよね。
        >これが万が一漏洩したらセッションハイジャックの危険が
        >あります。
        それは「CSRF対策・CSSXSS対策」とは別の話ですよね。 批判するにしても、あくまで別の話として批判するべきですよね。
    • たぶん、同じセッションIDを含んでいる他のページをGETで取得できる場合、そのセッションIDは容易に類推可能なものになってしまうからじゃないでしょうか。

      高木さんの対策は本質的には正しいのですが、「一致させる値を予測することは不能であるはずなので」という前提が崩れてしまったということだと思います。

      # あ、不能→不可能のTypo発見(^^;。

      親コメント
      • GETで取得できるページにはセッションIDを含めなければいいだけのことです。というかCSSXSSを想定してるなら含めてはいけません。
        逆にセッションIDを(もしくはワンタイムトークンなら何であれ)含める必要があるページは、POSTで生成しなければどうセッションIDと無関係なランダム値にしても意味ありません。
        • > GETで取得できるページにはセッションIDを含めなければいいだけのことです。

          その場合、ブラウザ側でクッキーが無効に設定されていたら、どうやってセッション管理するのでしょうか?正直に告白すると私はクッキーとhidden以外の方法でのセッション管理のやり方を知りません。URL埋め込みというのは却下でお願いします。 [aist.go.jp]

          金床さんの提案手法は、CSSXSSで仮にセッションIDが盗まれたとしても有効な対策と理解していたのですが、勘違い?

          ついでに書いておくと、今回の件でセッションIDはあくまでセッションを管理・追跡するためのIDとしてのみ使うべきであって、セキュリティを確保する目的で流用するのはまずいと、個人的には思うようになりました。大事な場面ではパスワードの再入力を求めるのと根っこはいっしょというか。

          もうひとつ、CSSXSSによって、hiddenがクッキーより危険になったのではなく、XSSのあるクッキーと同じレベルになってしまったと理解しているのですが、これも勘違い?

          親コメント
          • 別ACですが、
            その場合、ブラウザ側でクッキーが無効に設定されていたら、どうやってセッション管理するのでしょうか?正直に告白すると私はクッキーとhidden以外の方法でのセッション管理のやり方を知りません。
            Cookieオフのユーザでも使えるようにするなら、hiddenにセッションIDを入れます。何か問題がありますか?
            • > 何か問題がありますか?

              セッションIDを流用すると、すべての状態遷移をPOSTで実装しない限り、CSRF対策としては本来一致させる値を予測することは不可能な値を埋め込まなければならないのに、特定することが可能になってしまう(セッションIDと一緒)という、#914151で指摘した問題に戻ってしまいます。

              で、ワンタイムトークンを都度生成すれば、類推不可能という点においてはより望ましいのではないかという理解です。

              親コメント
              • このスレの流れは「ブラウザ側でクッキーが無効に設定されていたら、どうやってセッション管理するのでしょうか?」とおっしゃった話ではありませんでしたっけ?
                セッションIDを流用すると、すべての状態遷移をPOSTで実装しない限り、CSRF対策としては本来一致させる値を予測することは不可能な値を埋め込まなければ・・・・
                クッキーが使われていない前提ですから、元々すべての状態遷移をPOSTで実装するしかありません。
              • えーと、誰かも書いていたと思いますが、答えとしてすべてをPOSTで実装する(しなおす)、は現実的には無理かなと考えていました。

                で、
                > クッキーが使われていない前提ですから、元々すべての状態遷移をPOSTで実装するしかありません。

                ということであるなら

                CSRF対策にセッションIDを流用するために、すべての状態遷移をPOSTで実装する(しなおす)。
                というアプローチよりは、
                CSRF対策用にワンタイムトークンを生成して、操作完了後に消す
                というアプローチのほうが望ましいだろうというのが、「ワンタイムトークンは不要では」というコメントに対する私の意見です。

                親コメント
              • CSRF対策用にワンタイムトークンを生成して、操作完了後に消す
                というアプローチのほうが望ましいだろうというのが、「ワンタイムトークンは不要では」というコメントに対する私の意見です。
                は?
                セッション管理はどうしたんですか。セッション管理なしじゃ、動きもしないでしょうに。
              • 言葉足らずだったようで、すみません。

                後者のアプローチでは、セッション管理はセッションIDで行います。セッションIDとは別に、CSRF対策用のワンタイムトークンを生成して利用すると言うことです。そうすればPOSTで実装する必要が出てくるのは、ワンタイムトークンが利用される場面だけで済むんじゃないでしょうか。

                親コメント
              • 後者のアプローチでは、セッション管理はセッションIDで行います。
                クッキーが使われていない前提ですから、元々すべての状態遷移をPOSTで実装するしかありません。
              • > クッキーが使われていない前提ですから、元々すべての状態遷移をPOSTで実装するしかありません。

                議論が食い違っていますね。私の考えるCSSXSSでセッションIDが漏洩するとまずい理由は、セッションIDをCSRF対策に「流用」した結果、本来予測可能であってはならないCSRF対策用の鍵(トークンの方が正しい用語?)が特定可能になってしまうからです。セッションIDとは異なるワンタイムトークンを使えば、セッションIDからのCSRF対策用の鍵の特定はできなくなります。ここまでは良いでしょうか。

                セッションIDとCSRF対策用の鍵が別になっているような実装であれば、セッションIDをhiddenに入れた事によって(実はクッキーでも一緒なんですが)それが漏洩したとしても、対CSRF対策において、セッションID漏洩の結果もたらされる危険性は0となり、すべての状態遷移をPOSTで実装する必要はなくなります。もちろんハイジャック等の他の危険性には配慮する必要がありますが、そこはhidden、クッキーに関わらず「セッションIDが漏洩する」という事への対策の話となるので、CSRFの話とは別(の大事な)議論になると思っています。

                もしかすると、セッションIDについて、「漏れてはならないもの」と考えているか、「漏れるのはしょうがないもの」と考えているかの違いでしょうか。私は後者の立場で、セッションIDが漏れた場合でも、金床さんの提案したPOSTを使ってワンタイムトークンを新たに生成するという手法は、セキュリティを確保できる有効な対策になっており、また、「すべての状態遷移をPOSTで実装するしかありません。」という制限が生じるのは、セッションIDをクリティカルな場面に流用しようとしたがために導かれる、間違った結論だと思います。

                親コメント
              • いやだからさ、クッキー無効の前提で、どうやってセッション管理するの?って言ってるでしょ。まずそれに答えてみなよ。そうすれば君がおかしな思考に陥っていることに気づくよ。
              • だからhiddenでって、、、あ。

                長々とすみませんでした。恥ずかしながらようやく理解できました。

                <form method="get" ...> + hidden があるじゃんというまさしく馬鹿な思い込みをしていたのですが、私が自ら却下したURL埋め込みと等価なんだから当然だめですね。失礼しました。あわせて、こんな私にお付き合いいただいてありがとうございました。

                親コメント
      • だからそれは、ブラウザーに脆弱性がある場合の話では?

        ブラウザーに脆弱性があっても大丈夫なようにウェブアプリを作ることなんて不可能でしょ!
        • > ブラウザーに脆弱性があっても大丈夫なようにウェブアプリを作ることなんて不可能でしょ!

          一般論としてはその通りだと思います。

          今回のケースは、言ってしまえば(ある特定のブラウザの)影響の大きい深刻なバグが放置されており、その対処法が発表されただけとも解釈できるんですが、私があの手法を評価しているのは、今後同様のバグが発見された場合でも、この手法をとっていれば回避可能であると思える点です。

          あの文書の隠れた肝は、ログインからログアウトまでという比較的長い時間保持されるような情報を鍵として流用することの危険性を指摘し、ある特定のクリティカルな操作のためだけに鍵を準備して、事が済んだら即座に消す、という手法の提案を行ったという所にあるんじゃないかなあと思っているんですが、どうでしょう。

          親コメント
    • 先の#913853 [srad.jp]を読み返して、どうも誤解の余地が大きいような気がしたので補足します。

      僕の主張は、ワンタイムトークンを使うこと一切が不要である、というものではありません。それを明確にするため、サブジェクトを変えました。

      セッション ID を使うよりワンタイムトークンを使う方が安全かもしれない要因はいろいろあると思います。ただ、それは元の話題とは別の話と考えています。

      高木氏の「クロスサイトリクエストフォージェリ(CSRF)の正しい対策方法 [takagi-hiromitsu.jp]」での「簡潔な対策方法」はワンタイムトークンを使わないものでしたが、金床氏は、主要なブラウザである IE に XSSCSS 問題があるためワンタイムトークンを使う必要がある、と主張していました。それに対して、僕は、金床氏の「正しい対策その1」での XSSCSS 対策はリクエスト1を POST にすることによってなされているのであって、ワンタイムトークンを使うというのは無関係じゃないの? ということを書いたつもりでした。

      そもそも高木氏がこのページを書かれた背景には、 CSRF 攻撃の脅威が増しているのに正しい対策方法はよく知られていないという背景がありました。そこで、高木氏は、なるべく少ないコード変更でできる CSRF 攻撃対策として、「今までワンタイムトークンを使っていないなら、ワンタイムトークンを生成するコードを新たに書かなくても、前から使っているはずのセッション ID を hidden フィールドにも入れて一致をチェックするだけで対策になるんですよ、ほら簡単でしょ、だからすぐ対策しましょう」ということを書かれたのだと理解しています。

      僕は、 hidden フィールドに入れるのは cookie に入れるのと同じセッション ID でもかまわないというのは重要なポイントだと思うので、そうではないとする金床氏の主張に#913853で反論しました。しかし、それは、ワンタイムトークンを使うのと比較してセッション ID を使う方が安全性の面で良いと主張する趣旨ではないし、ましてやワンタイムトークンの意味をすべて否定する趣旨でもありません。
      --
      鵜呑みにしてみる?
      親コメント
      • とあるところで金床氏のページが残っているのを見つけたので読み返しました。すると、僕は根本的なところで金床氏のページを読み間違えていることがわかりました。
        • 金床氏は、ワンタイムトークンを使わずにセッション ID を使う方法の欠点を説明していた。
        • 金床氏は高木氏の対策でリクエスト1を POST にしたものについて言及しており、この方法で CSSXSS 問題には対策できている (ただし上の欠点があるため推奨しない) ことを述べていた。
        公開停止された文章なので引用しませんが、どちらも、「誤った対策その1: セッションIDをトークンとして使う」の最後2個の段落に書かれていました。

        この読み間違いの結果、#913853 [srad.jp]と#914676 [srad.jp]にて、金床氏のページの内容について多くの誤りを書いてしまいました。金床氏に謝罪いたします。また、これらのコメントを読んでいただいた方にも、申し訳ありません。

        それで、現状はというと、僕は金床氏の主張が何であったか、よく理解できていない、ということになってしまいました。すみません。さらに、既に公開を停止された文章の主張が何であったかを今更検証することにあまり価値を見出せません。新バージョンを書かれるかもしれないとのことなので、それが公開された後で時間があったら、何かコメントするかもしれません。
        --
        鵜呑みにしてみる?
        親コメント
        • 今回、
          ・技術的にすべきこと
          ・技術論
          の二つが語られていると思います。

          セッションIDを使う技術屋としては
          ・A案が危険という人が提案したB案
          ・B案もA案も同じだ
          という二つの意見が合った場合、
          ・B案はむしろ危険
          ・B案は高コスト
          とかでない限り、B案をとりたいと思うのです。

          通常、ワンタイムトークンを作るなら言語に備え付けのセッションIDを用いて実装すると思うのですが、違うのでしょうか?
          なので、
          ・ログイン中変わらないセッションID
          ・作業ごとに変わるセッションID
          の二つを使用せよ、という事だと理解しているのですが。

          どうせひとつの手法では解決できない(パスワードの変更には旧パスワードを入れたり堅めに作る)ので、今技術屋さんは何をすべきなのか、というのを誰か教えてもらえないでしょうか?

          CSSXSSとCSRFを分けて考えるべきとかは、現場的な対応ではないかと。

          お仕事関係なのでACにさせてください。
          • 今更書いても、もう読んでいないかもしれませんが……。
            セッションIDを使う技術屋
            との表現から、ウェブサイトの開発に関わる技術者のかたと判断し、その前提で書きます。

            僕は開発経験がほとんどありませんし、その他の考察も足りないので、あなたの疑問には答えられません。

            ただ、興味深いと思ったのは、お仕事としてウェブサイトに関わっている人と、ウェブサイトの開発の経験がほとんどない僕のような者とでは、やっぱり問題意識というか興味の対象が違うのだなあ、という点です (当然といえば当然ですが)。

            僕の興味の対象はセキュリティの問題そのものであって、例えば今回の問題に関連する疑問は次のようになります。
            • CSSXSS 問題とはどういう問題であって、どういうセキュリティ上の影響があって、どういう対策ができるのか。
            • CSRF 攻撃の本質は何で、対策するには何が必要なのか。
            • 今回初めて考えた問題: CSSXSS 問題対策と CSRF 攻撃対策を別々に施せば両方の対策になるのか、それだけでは駄目なのか。
            で、今回一番重要なのはこの3番目だと思っているわけです。

            それに対し、
            CSSXSSとCSRFを分けて考えるべきとかは、現場的な対応ではないかと。
            というのは半分頷けます。

            上のような疑問に対して、調べたり考えたりして答えを見つけていっても、直接的に開発の現場の役には立たないかもしれません。結局のところ、金床氏の「正しい対策その1」が安全性の面でもそれ以外の面でも満足いくものなら (実際、このストーリーに対するコメントをざっと見たところでは、金床案の安全性に疑問を投げかけている人はいないようです)、「高木案+リクエスト1を POST に」が安全か危険かなんて検討する必要はないわけですし。

            (例えばの話、僕がウェブサイトの開発をどこかの会社に依頼したとして、ある問題に対して全面的に満足いく方法があるのに、「それ以外の方法でもいいかどうか」を延々と検討されたら、たぶん怒ります。)

            でも、上のような疑問について考えることは、安全な対処法を自分で考えたり、人が提案する対処法の安全性を検討したりするときに役に立つと思います。安全性について、開発の現場で自分で対処法を考えなければならない状況がどの程度あるかはわからないのですが、開発の現場でこういうことを考えることも、何かの役には立つのではないか、と期待するのですが。
            --
            鵜呑みにしてみる?
            親コメント
          • 現場的対応としてCSSXSSを防がないとなると、
            CSRF以前にCSSXSSの危険回避のために、
            見られてはまずいページは全部POSTにしないといけません。そこはオーケー?

            で、全部POSTにしたならCSRF対策用のキーは何でもよい
            わけです。漏れませんから。
            これでわかりましたか?

海軍に入るくらいなら海賊になった方がいい -- Steven Paul Jobs

処理中...