[追記] 今度こそ結論。Cookieこそ盗めなくなるが、Ajaxでなんとでもできるので寄与しない
なんと著者から反応がありました。それによると、別のパスからでもXHRやFetchで自由に操作できてしまうので、Cookieを盗むまでもなく被害者の権限で攻撃ができる、ので安全性には寄与しない、とのことです。
確かによく考えるとその通りです。Cookieを盗めるか盗めないか、という点ばかりに目を取られていました。
詳しくはこちらから。
以下未修正ですのでご注意ください。
先日体系的に学ぶ 安全なWebアプリケーションの作り方を読んでいて、疑問をいだきました。
4.8.2 クッキーのセキュア属性不備の項で、CookieのPath属性について、
Path属性を指定しても、安全性が高まるわけではないことに注意してください。その理由は、JavaScriptの同一オリジンポリシーがホスト名単位であり、ディレクトリ単位ではないからです。
と書かれていたのですが、Path属性の指定が安全性に寄与しないのはなぜか、ということについて詳しい説明がありません。同一オリジンポリシーとなんの関係があるのでしょう?
気になったので調べてみました。
結論。Path属性は特殊な状況下ではある程度安全性に寄与する
Path属性は、これを設定してCookieを発行するあるパス(以下「自身のパス」)にサーバサイドのプログラムを書き換えられるような脆弱性がなく、同一オリジン内の別のパスにそのような脆弱性がある場合に、そのパスへのCookieの漏洩することを防ぐことができます。
ただし、HttpOnly属性か、HTTPヘッダにX-Frame-Option: DENY
が設定されている場合に限ります。そうでない場合はXSSによって漏洩します。
そもそもPath属性はどのように安全性に寄与しそうか?
Cookieは発行時に設定されたドメインにのみ送信されます。Path属性があると、さらに設定されたパスにのみ送信されるよう、追加で制限されます。
例として、あるパス(/cart/
)以下にログインフォームがあり、ログイン時にセッションIDをCookieで発行する場合、Path属性を/cart/
に設定しておけば、別のパス、たとえば/items/
以下からはこのCookieを参照できなくなると考えられます。
本当にそんな単純な話なのか?
単純に上記の通りに働くのであれば、「体系的に学ぶ 安全なWebアプリケーションの作り方」に、あのようには書かれていないのではないかと思います。
そのため、なんらかの落とし穴がないか調査しました。その結果、以下の2つの情報源に、Path属性が安全性に寄与しないという情報が見つかりました。
frame要素を使うと、Path属性を設定したCookieでも別のパスからJavaScriptでアクセスできる
以下のページに詳しい情報があります。frame要素でCookieを盗みたいパスを読み込むことで、parent.(frame名).document.cookie
経由でPath属性が設定されているCookieをほかのパスから盗み出すことができます。
高木浩光@自宅の日記 - 共用SSLサーバの危険性が理解されていない
via CookieのDomain属性は 指定しない が一番安全 | 徳丸浩の日記
Chrome, Firefoxのそれぞれ最新版で実験しましたが、現在のブラウザでも動作するようです。同一オリジンポリシーのことを考えれば、この挙動はおそらく仕様なのでしょう。
また、「体系的に学ぶ 安全なWebアプリケーションの作り方」中で"その理由は、JavaScriptの同一オリジンポリシーがホスト名単位であり、ディレクトリ単位ではないからです。"とあった個所は、この仕様について指しているのではないかと思われます。
ただしこの仕様については、HttpOnly属性で回避できます。最近であれば、HTTPレスポンスヘッダにX-Frame-Option: DENY
(当然、SAMEORIGIN
では駄目)を設定することでも回避できます。
そのためPath属性を設定していても別のパスにXSSがあればCookieの漏洩を回避できないからPath属性は安全性に寄与しない、とは言えないでしょう。
Cookieの仕様であるRFC 6265がセキュリティは Path 属性に依存できない
と言っている
RFCで書かれているのであれば、考慮しないわけにはいきません。以下のページには、
所与のホストの中で,パスが異なるクッキーを互いに隔離することは、一見 有用であるが,セキュリティは Path 属性に依存できない( § セキュリティの考慮点を見よ)。
とあります。
Cookies: HTTP State Management Mechanism (日本語訳)
「セキュリティの考慮点」の方を見てみますと、Path属性を使っても、およそ以下の2点については安全ではない、とのことのようです。
「8.5. 機密性の弱点」より
クッキーはパスによる隔離を常に供するものではない。 ネットワークレベルのプロトコルでは、あるパスに対応して格納されたクッキーが,別のパスに向けて送信されることはないが、一部の UA は, HTML の document.cookie API などの “非 HTTP” API を介して,クッキーを公開する。
こちらは上記の、frame要素を使ってJavaScriptからアクセスする方法も含む問題と考えられそうです。つまり、同じようにHttpOnly属性で別途回避できる問題です。
「8.6. 完全性の弱点」より
Set-Cookie ヘッダが Path 属性をサポートしていても, UA は Set-Cookie ヘッダ内の任意の Path 属性を受容するので、 Path 属性は,いかなる完全性の保護も供さない。 例えば, http://example.com/foo/bar に向けた要請に対する HTTP 応答は、 Path 属性 "/qux" のクッキーを設定できる。
こちらはCookieの発行時の話であって、セッション固定攻撃には確かにつながります。そしてPath属性ではそれを軽減できないという話で、Path属性によって漏洩を防げるかどうかについては無関係です。
ということで、"セキュリティは Path 属性に依存できない"というのは、Path属性が安全性に寄与しないという話ではなく、Path属性だけでは対応できないセキュリティの問題もある、という程度と考えてよさそうです。
結論
ここまでの調査から、以下のことがわかりました。
- Path属性による制限は、JavaScriptからは回避されてしまう。
- Path属性による制限は、セッション固定攻撃を防ぐことはできない。
- それ以外の場合にはPath属性による制限は有効。
3の「それ以外の場合」には、別のパスのサーバサイドのプログラムが攻撃を受けるなどして、そちらからCookieを盗み出せるような場合が含まれます。つまり、Path属性はそのような攻撃を防げると考えられそうです。
具体的にはどのような場合で有効でしょうか? 以下の2つのケースが考えられます。
- 別のパスだけ、サーバサイドのプログラムが書き換えられる脆弱性がある。
- 昔あったような、同一オリジン内で、複数の利用者がそれぞれのパスを所有している。
1については、そのようなことを考慮してPath属性による制限をつけるのは、コスト対費用的にあまり意味がなさそうです。
2については、Cookieの漏洩を考慮しなくても危険だらけのため、そのような状況で重要なアプリケーションを動かさないことがまず重要でしょう。
ということで、Path属性は安全性に寄与しないわけではないが、とはいえ考慮すべきほど意味があるとも考えられない、という結論に達しました。
つまり、「体系的に学ぶ 安全なWebアプリケーションの作り方」の記述はおそらく間違えです。
とはいえ私はセキュリティは専門ではなく、特に攻撃側には疎く、この記事に書いた以上の調査・実験もしていないため、この結論も確実とは言い切れません。詳しい情報をお持ちの方がいたら、ぜひご教示ください。
この記事のライセンス
この文書はCC BY(クリエイティブ・コモンズ表示4.0国際ライセンス)で公開します。