それでは、解答を説明します。
設問: チートシート旧版の翻訳であるJPCERT/CC訳(以下の引用部分)を元に以下の設問に答えよ。
引用(再掲)
Cookie の二重送信
Cookie の二重送信は、Cookie およびリクエストパラメーターの双方でランダムな値を送信し、サーバー側で Cookie の値とリクエストの値が等しいかどうか検証する手法です。
ユーザーがサイトにログイン するとき、サイトは暗号強度の高い疑似ランダム値を生成し、その値を Cookie としてユーザーのマシンに、セッション ID とは別に送ります 。どんな形であれ、サイトはこの値を保存しておく必要はありません。次にサイトは、機密に関わる送信にはすべてこのランダム値が非表示のフォーム値 (または他のリクエストパラメーター) および Cookie の値として含まれていることを確認します。同一生成元ポリシーにより、攻撃者はサーバーから送信されるどんなデータも読み取ることができません。また、Cookie の値を変更することもできません。攻撃者は、任意の値を悪意のある CSRF リクエストに添付して送信できますが、Cookie に保存されている値は、変更することも、読み取ることもできません。Cookie の値と、リクエストパラメーターまたはフォームの値は同じにする必要があるので、攻撃者はランダムの CSRF 値を推測できない限り、フォームを正常に送信できません。
Direct Web Remoting (DWR) の Java ライブラリバージョン 2.0 には、CSRF 対策として、透過的に Cookieの二重送信を行う機能が組み込まれています。
設問(1)
引用部分の解説には技術的な間違いがある。それを指摘せよ解答(1)
以下の箇所が間違いです。同一生成元ポリシーにより、攻撃者はサーバーから送信されるどんなデータも読み取ることができません。また、Cookie の値を変更することもできません。Cookieの保護は同一生成元ポリシーではなく、独自のルールによります。そもそも「同一生成元」とは、ホスト、ポート番号、スキームのすべてが一致している状態ですが、Cookieは、以下のルールに従います。
- ホスト: domain属性の指定があるばあいはdomainに指定したドメインおよびそのサブドメイン。ない場合はSet-CookieしたホストにのみCookieが送信される
- ポート: RFC 6265によると、Cookieは同一ホストの異なるポートをまたがって共有される
- スキーム: HTTPとHTTPSで相互にCookieの読み取り、書き込みができるが、secure属性が指定されたCookieはHTTPSの場合のみ送信される
設問(2)
クッキーの二重送信でCSRF保護できないシナリオを複数指摘せよ。OWASP原文の改定で指摘されていないシナリオを指摘すると加点となる解答(2)
以下、攻撃対象サイトが www.example.com というホスト名である前提で説明します(シナリオ1を除く)。シナリオ1: クッキーモンスターバグの影響があるサイト
以前にもブログ記事で説明したように、Windows8.1以前のIE11にはクッキーモンスターバグがあり、地域型JPドメイン名や都道府県型JPドメイン名などで、不正なdomain属性のCookieが作れてしまいます。例えば、東京都のドメイン名は metro.tokyo.jpですが、私が所有するドメイン名(tokumaru.bunkyo.tokyo.jpやkawaguchi.tokyo.jp)で、domain=tokyo.jpというCookieがSet-Cookieできるため、tokenのクッキーを汚染する攻撃ができます(Windows8.1以前のIE限定)。このシナリオは以前下記の記事で紹介しました。IEのクッキーモンスターバグはWindows 10で解消されていた
クッキーモンスターバグの影響を受けるのは、日本のドメイン名ばかりではありません。Public Suffix Listに掲載されたドメイン名のうちIEが対応していないものはすべて該当することになります。馴染み深いドメイン名の例としては以下があります。
- blogspot.com
- herokuapp.com
- cloudfront.net
Heroku上に上記をホスティングしました。下図はWindows8.1上のIE11で閲覧した様子です。<?php session_start(); $token = "hello-csrf-trap"; setcookie("token", $token, 0, '/', 'herokuapp.com'); ?><body> <form action="https://csrf-vul.herokuapp.com/chgmail.php" method="post"> <input name="mail" value="evil@example.com"> <input name="token" value="<?php echo $token; ?>"> <input type=submit> </form> </body>
先程のリンクでmypage.phpを閲覧した後、この罠(リンク)を閲覧します。「クエリ送信」ボタンをクリックすると下記のようにメールアドレスが変更されます。
Public Suffix Listに対応したブラウザ(Google Chrome、Safari、FirefoxやWindows10上のIE11とEdge)であれば、上記の攻撃は成立しません。
シナリオ2: サブドメイン型 レンタルサーバーの場合
Public Suffix Listに対応したブラウザであっても、サブドメイン型として提供されるレンタルサーバーであれば、上記と同じ攻撃が成立します。hoge.examle.comやfoo.example.com等のドメイン名が選択できるレンタルサーバーであれば、hoge.example.com 上のサイトを攻撃するCookieを
foo.example.com上のサイトで生成できる(domain=example.com)
ことになります。
このケースはブラウザの種類を問わず、また他の脆弱性などに依存しないので、特に注意が必要でしょう。
シナリオ3: example.comのサブドメインのホストにXSS脆弱性がある場合
通常クロスサイトスクリプティング(XSS)脆弱性は同一生成元ポリシーの範囲のみで影響を受けるので、他のサブドメインまで影響が及ぶことはありませんが、クッキーの生成に関してはサブドメインも影響を受けるため、example.comのサブドメインにどれか一つでもXSS脆弱性があるサイトがあれば、www.example.comで有効なtokenのcookieを発行できます。このシナリオは、改定後のCSRF Prevention Cheat Sheetでは、Double Submit Cookieの項の「a) While it's true that hellokitty.marketing.example.com cannot read cookies…」以下の箇所に解説があります。
シナリオ4: HTTPヘッダインジェクションなどCookie設定可能な脆弱性がある
攻撃対象サイトにHTTPヘッダインジェクション等Cookie設定が可能な脆弱性がある場合、当該サイトで有効なtokenのCookieを発行できます。他の対策ではこの影響は受けないので、二重送信Cookie特有のリスクということになります。シナリオ5: HTTPとHTTPS混在のサイトでHTTP側にXSS脆弱性がある
シナリオ3の変形です。XSSは同一生成元ポリシーの範囲のみで影響があるということは、HTTPとHTTPS混在のサイトの場合、HTTP側のXSS脆弱性はHTTPS側には影響がなく、逆に、HTTPS側のXSS脆弱性はHTTP側では影響がありません。しかし、HTTP側で生成したCookieはHTTPS側でも有効なため、二重送信Cookieに関してはHTTP側にXSS脆弱性があれば、HTTPS側機能にも影響があります。この問題も、他のCSRF対策にはない、二重送信Cookie固有のリスクといえます。
なお、同一オリジン内にXSS脆弱性があれば、他のCSRF対策も回避されますが、同様の攻撃はXSS単体でも可能(同一オリジンからのXMLHttpRequest等で)なので、XSSでCSRF対策が回避されることは気にしても仕方ないと言えます(CSRFの有無によりリスクは増加しない)。
シナリオ6: 通信経路上でトークンCookieを上書きする
以下の記事で説明した問題です。通信経路上に攻撃者がいる場合でも、HTTPSを使えば通信内容の盗聴や改ざんを防止できますが、中間者攻撃によるCookieの改変はHTTPSを使っても防げないという問題です。HTTPSを使ってもCookieの改変は防げないことを実験で試してみた
常時TLSが一般的になりましたので、この経路による攻撃は大半のサイトが該当すると考えられます。「中間者攻撃なんて気にしないといけないの?」という感想もあるかもしれませんが、HTTPSの主要な目的は中間者攻撃など通信経路上の攻撃を防ぐことなので、HTTPSを使う以上は気にするべきでしょう。
このシナリオは、改定後のCSRF Prevention Cheat Sheetでは、Double Submit Cookieの項の「b) If an attacker is in the middle, …」以下の箇所に解説があります。
※サイトの真正性確認だけのためにHTTPSを使うという考え方もあるとは思いますが