2011年9月27日火曜日

都道府県型JPドメインがCookieに及ぼす影響の調査


JPRSからのプレスリリース『JPRSが、地域に根ざした新たなドメイン名空間「都道府県型JPドメイン名」の新設を決定』や報道などで「都道府県型JPドメイン」というものが新設されることを知りました。
都道府県型JPドメインとは、現在活発に使われていない地域型ドメインを活性化する目的で、地域型ドメインの制約(ドメイン名が長い、一人・一団体あたり1つまで)を簡略化しようというもののようです。
しかし、現在の地域型ドメインは、ブラウザにとって処理がややこしいもので、IEなどは昔からまともに対応していません。このため、Cookie Monster Bugという脆弱性になっているという経緯があります。このルールをさらに複雑にすることになるということから、ブラウザセキュリティに関心の高い人たちが騒ぎ始めています。

そこで、高木浩光氏の日記「JPRSに対する都道府県型JPドメイン名新設に係る公開質問」の以下の部分に関して、調査をしてみました。
何もしなければ、「都道府県型JPドメイン名」の登録が始まっても、cookieを利用できないなどの欠陥ドメイン名となることが予想される。
調査は、「何もしない」状態、すなわち現在のブラウザで、都道府県型ドメインをシミュレートして、Cookieの受け入れられる状態を確認しようというものです。

まず、ドメインとしては、地域型ドメイン toku.tsu.mie.jp と、都道府県型JPドメイン toku.mie.jp の2種類を実験環境に用意しました。

現在の地域型ドメインは、原則として4レベルのドメインになります。但し、都道府県のドメイン(pref.mie.jp等)は例外です。これに対して、都道府県型JPドメインは3レベルのドメインになることがウリです。都道府県型ドメインの「ややこしさ」とは、この4レベルと3レベルのドメインが混在することで、その切り分けには、市町村の名前全て(tsu.mie.jpなど)をブラウザ側に保持する必要が生じることです。

ホスト名(FQDN)としては、ドメインそのものと、www.で始まるもののの2種類を用意しました。すなわち、ホスト名は以下の4種類です。

地域型ドメイン(toku.tsu.mie.jp)に属するもの
  • toku.tsu.mie.jp
  • www.toku.tsu.mie.jp
都道府県型JPドメイン(toku.mie.jp)に属するもの
  • toku.mie.jp
  • www.toku.mie.jp
これらホストに対して、以下の5種類のdomain属性を持つCookieをセットしてみて、どのCookieが受け入れられるかを調べました。
  • mie.jp
  • tsu.mie.jp
  • toku.mie.jp
  • www.toku.mie.jp
  • toku.tsu.mie.jp
  • www.toku.tsu.mie.jp
まず、Firefox 6.0.1での結果を下表に示します。

Firefox 6.0.1
Cookie 地域型ドメイン 都道府県型JPドメイン
toku.tsu.mie.jp www.toku.tsu.mie.jp toku.mie.jp www.toku.mie.jp
mie.jp
tsu.mie.jp
toku.mie.jp ×
www.toku.mie.jp
toku.tsu.mie.jp
www.toku.tsu.mie.jp

ホスト www.toku.mie.jpに対して、domain=toku.mie.jpのCookieが受け入れられていません。これは、現在の地域型ドメインのルール(4レベルのドメイン)に則したものです。
一方、ホストtoku.mie.jpに対して、domain=toku.mie.jpのCookieが受け入れられているのは規約上微妙な気がします。そのような地域型ドメインのホストは現在の仕様上はないはずですが、現にホストが存在していることを優先して、Cookieを受け入れているのでしょうか。

次に、Chrome 14.0.835.168 および 15.0.874.24 beta-m での結果を示します。どちらも同じ結果です。

Chrome 14.0.835.168 15.0.874.24 beta-m
Cookie 地域型ドメイン 都道府県型JPドメイン
toku.tsu.mie.jp www.toku.tsu.mie.jp toku.mie.jp www.toku.mie.jp
mie.jp
tsu.mie.jp
toku.mie.jp × ×
www.toku.mie.jp
toku.tsu.mie.jp
www.toku.tsu.mie.jp

Firefoxの場合と1箇所異なっています。domain=toku.mie.jpのCookieはいかなる場合にも受け入れられていません。これは現在の地域型ドメインの仕様を重視した結果と思われます。
その結果、高木浩光氏の言われる「cookieを利用できないなどの欠陥ドメイン名と」なっています。現状のChromeの仕様が仮にこのままだとすると、都道府県型JPドメインであっても3レベルのままでは使用できず、www.などのサブドメインをつけなければ使用できないことになります。

続いて、IE9での結果です。

IE9 (9.08112.16421)
Cookie 地域型ドメイン 都道府県型JPドメイン
toku.tsu.mie.jp www.toku.tsu.mie.jp toku.mie.jp www.toku.mie.jp
mie.jp ○(cm) ○(cm) ○(cm) ○(cm)
tsu.mie.jp ○(cm) ○(cm)
toku.mie.jp
www.toku.mie.jp
toku.tsu.mie.jp
www.toku.tsu.mie.jp

よく知られているように、IEは地域型ドメインに対してCookie Monster Bugがあります(cmをつけた箇所)。Cookie Monster Bugとは、本来受け入れてはならない上位のドメインについてCookieを発行できるバグのことです。
現在の地域型ドメイン、例えばtoku.tsu.mie.jpでサイトを運営していると、mie.jpドメインでのCookieが発行できるわけですから、これはpref.mie.jp(三重県のドメイン)やcity.tsu.mie.jp(津市のドメイン)にも適用されるCookieが発行できることになります。これにより、セッションIDの固定化攻撃がやすやすくなるなどの影響かあります。
都道府県型JPドメインの運用が始まった後のIEの対応はわかりませんが、長年地域型ドメインのCookie Monster Bugを放置しているという実績から考えると、都道府県型JPドメインにすぐさま対応するは思えません。

次に、Safariでの結果ですが、これはFirefoxと同じパターンです。

Safari 5.0.2(7533.18.5)
Cookie 地域型ドメイン 都道府県型JPドメイン
toku.tsu.mie.jp www.toku.tsu.mie.jp toku.mie.jp www.toku.mie.jp
mie.jp
tsu.mie.jp
toku.mie.jp ×
www.toku.mie.jp
toku.tsu.mie.jp
www.toku.tsu.mie.jp

最後にOperaでの結果です。

Opera 11.51
Cookie 地域型ドメイン 都道府県型JPドメイン
toku.tsu.mie.jp www.toku.tsu.mie.jp toku.mie.jp www.toku.mie.jp
mie.jp ○(cm) ○(cm) ○(cm) ○(cm)
tsu.mie.jp ○(cm) ○(cm)
toku.mie.jp
www.toku.mie.jp
toku.tsu.mie.jp
www.toku.tsu.mie.jp

この結果を見て驚きました。OperaにもCookie Monster Bugがあります。最初調査方法の問題かと思い、調査方法を変えて調べてみましたが、結果は変わりません。どうも最近のOperaには地域型ドメインに対するCookie Monster Bugがあるようです(*1)。
この結果はIEと同じですので、影響もIEと同じです。

まとめ
現在のブラウザの仕様が変わらないという前提で、都道府県型JPドメインの運用が始まった際の影響を調べました。
Firefox、Chrome、Safariについては、3レベルのドメインについてCookieが受け入れられない場合があります。この結果、Chromeの場合3レベルのドメインではCookieがまったく利用できません。FirefoxとSafariでは、ホスト名そのままのCookieは利用できますが、サブドメイン間でCookieを共有できないという問題につながります。
IEとOperaについては、Cookie Monster Bugのため、Cookieを安全に利用できないという問題があります。
この結果をどう評価するかですが、私は、高木浩光氏の日記で指摘された「cookieを利用できない」という欠陥よりも、IEとOperaのCookie Monster Bugの方が気になります。とくに、IEのシェアは現在でもかなり高いため、地域型ドメインおよびその後継である都道府県型JPドメインでは、Cookieを安心して使えず、セキュリティ上の大きな障害になると考えます。

*1: 地域型ドメインと都道府県型JPドメインのシミュレーションには、DNSキャッシュサーバーにて実験用のドメインを指定する方法を最終的に用いました。

2011年9月26日月曜日

PostgreSQLは標準でバックスラッシュをエスケープしない仕様になった

PostgreSQL9.1の仕様変更にて、デフォルト時の設定として、standard_conforming_stringsがonとみなされるようになりました。この仕様変更により、デフォルト設定でのPostgreSQLは、バックスラッシュをエスケープする必要がなくなり、ISO規格のSQLと同様のエスケープルール(シングルクォートを重ねるのみ)となります。

PostgreSQLの文字列リテラルは、元々MySQL同様に、バックスラッシュをエスケープする仕様でした。その後、リリース8.1にて、設定パラメータ standard_conforming_strings が追加され、この値が on の場合、バックスラッシュをエスケープしない(ISO規格と同様の)仕様となりました。従来のリリースでは、standard_conforming_stringsを指定しない場合offとみなされていました。これは、後方互換性維持のためでしょう。

リリース8.1のドキュメントには以下のように記述されています。
standard_conforming_stringsの値は読み取りのみです。アプリケーションでは、この値を読み取ることで、どのようにバックスラッシュが解釈されるかが分かります。(また、このパラメータが存在するかどうかで、E''文字列構文がサポートされているかどうかが分かります。)今後のリリースでは、standard_conforming_stringsは真になる予定です。
ここで、E''文字列構文という用語が出てきました。これは、PostgreSQL固有の機能で、standard_conforming_stringsの設定に関わらずバックスラッシュによるC言語風のエスケープを行う文字列形式です。

ここで、standard_conforming_strings設定と、バックスラッシュのエスケープ要・不要の関係を下表にまとめました。

standard_conforming_strings設定とバックスラッシュのエスケープの関係
standard_conforming_stringsリリース9.0.4以前リリース9.1以降
offエスケープ要エスケープ要
指定無しエスケープ要エスケープ不要
onエスケープ不要エスケープ不要

表からも分かるように、PostgreSQLリリース9.1にバージョンアップして挙動が変わるのは、standard_conforming_stringsの設定をしていない場合です。この場合は、standard_conforming_stringsをoffにすることで従来通りの挙動となります。

しかし、standard_conforming_stringsの設定を変更しない場合は、既存のアプリケーションはどのような影響を受けるでしょうか。以下、PHPとPerlで記述されたアプリケーションについて、この変更の影響を検討してみます。

PHPのPostgreSQL関数(pg_xxxx)やPDOなどには、SQL文字列のエスケープ用の関数が用意されています。PostgreSQL関数ではpg_escape_string関数、PDOではquoteメソッドが該当します。これらを使用している場合、standard_conforming_stringsのオプションを自動的に反映して、適切にエスケープしてくれます。
DBI/DBDのPgやPgPPを使っている場合、quoteメソッドで文字列をエスケープしている場合も同様です。
これらの挙動を「a\'」という文字列がどうエスケープされるかによって調査しました。

standard_conforming_stringspg_escape_stringquote(PDO)  quote(Pg)quote(PgPP)
offa\\'''a\\'''E'a\\'''E'a\\\''
指定無しa\'''a\'''E'a\\'''E'a\\\''
ona\'''a\'''E'a\\'''E'a\\\''
※各モジュールのバージョン
PHP: 5.3.8
Pg: 2.18.1
PgPP: 0.08

quoteという名前のメソッド(PDO, PG, PgPP)は、いずれもエスケープするだけでなく、シングルクォートで文字列を囲むことにご注意下さい。
上表から、これらの関数・メソッドを使っていれば、文字列は正しくエスケープされることが分かります。pg_escape_stringとPDOのquoteメソッドは、通常の文字列リテラル形式を用い、バックスラッシュのエスケープをstandard_conforming_stringsに応じて切り替えています。
これに対して、PerlのPgとPgPPは、E''文字列形式を用いることによって、standard_conforming_stringsの影響を回避しています。また、プレースホルダを使ってSQLを呼び出している場合も、standard_conforming_stringsの影響は受けません。

一方、エスケープにaddslashesや自作のエスケープ関数を用いている場合は、対応が必要となります。また、PgPPの古いバージョンを使っている場合もstandard_conforming_stringsの設定を考慮しないので注意が必要です。

既存アプリケーションのリリース9.1対応では、standard_conforming_stringsの意味を変えない方が無難だと思います。このため、既存アプリケーションでPostgreSQLのバージョンを9.1以降に変更する場合は以下のようにすればよいでしょう。
  • standard_conforming_stringsを明示している場合はそのままでよい
  • standard_conforming_stringsを明示していない場合はoffを指定する
これにより、standard_conforming_stringsのデフォルト値の変更を吸収できます。

一方、新規アプリケーション場合は、standard_conforming_stringsを指定しない(あるいはonにする)と良いでしょう。その理由は、こちらの方がISOのSQL標準であり、またバックスラッシュをエスケープ対象にすると、セキュリティ上の問題になりやすいからです。MySQLとの互換性を気にする人もいるでしょうが、PDOやDBIなどの抽象度の高いライブラリを使って記述することにより、エスケープ対象の文字をアプリケーション側で意識する必要はなくなり、互換性も向上します。
さらに言えば、プレースホルダを用いてSQL呼び出しすることを強く推奨します。これにより、そもそも文字列リテラルのエスケープが必要なくなり、性能・互換性・セキュリティともに改善されます。

[PR]
安全なWebアプリケーションの作り方」電子書籍版9月28日(水)販売開始します。くわしくはこちら

フォロワー