Home

日記
Zend Frameworkをどう使うか その19Edit

フレームワークとしての基本機能を一通りチェックしたんで、実際に何か(ある程度実用的な)アプリケーションを作ろうかと思って試してみたんだけど、現時点ではまだサンプルアプリ以上のものを作るのはきついな。

もちろん動くものを作るだけならなんとかなるんだけど、Zend Frameworkベースのアプリケーションとして、ある程度の将来互換性も確保できるように作ろう、とか思うと現時点の完成度ではまだ無理だ*1

一応Controller周りは結構完成度が高そうなんで、そこだけならばいけそうではある。かなりフィックスした仕様に見えるし、たとえデフォルトでの挙動が変更されたとしても、現状の拡張性の枠組みの中でカバーできるであろう柔軟性を備えている。プラグインの機構も応用範囲が広そうだ。

Viewに関しては、現状が最終仕様とはとても思えないんで、おそらくまだまだ互換性のない仕様変更があるだろう。っつーか、現在のZend_Viewを使うくらいだったら、もっとこなれた他のテンプレートエンジン(Smartyとか)を使った方が、現時点ではずっとましだろう。

Zend_Logは、ログの保存がstaticメソッドに集約されたという設計はいいんだけど、デフォルトでCompositeじゃないのが使いにくい。自前のComposite Adapterとかを使ってカバーするという手もあるけど、その辺には仕様変更もありそうだし、現時点ではまだPEAR Logを使っておいた方がましかもしれない。

Zend_Db周りは非常にビミョー。Zend_Db_Adapterはあれで十分なんで、そのままいけるかなーと思いつつも、O/Rマッパー系は現状では実用レベルじゃないよなー。1テーブル単位のselectしかサポートしないO/Rマッパーで完結できるような設計なんて現実的じゃないし、ちょっとでもjoinしたければとたんにO/Rマッパーはつかえなくなっちゃうし。

Zend_Db_Tableにjoin系の機能が追加されるのはいつなんだろう? 一応Zend_Db_Inflector::plural(複数形化)とか用意されているし、そっち方向の拡張を行う気はあるんだよね。

ただまあ、すぐに実装されるってことはなさそうだよなー。Zend_Db_Adapterには文句はないから、ひとまずそれ+SQL文でがりがり書くのが現時点では一番無難か? それとも他にいいO/Rマッパーはないかなー。でもZend_Db_Adapterと連動するとなると、無理だよなー。

*1 もちろんPreview Releaseなんだから、そのくらいの完成度であることに文句はない

Published At2006-03-29 00:00Updated At2006-03-29 00:00

日記
join機能の独自拡張Edit

「Zend_Db_Tableにjoinがあれば、現時点でも使う気になるのになー」ということで、試しに独自にjoin機能を実装してみることにした。

Zend_Db_Table、Zend_Db_Table_Row、Zend_Db_Table_Rowsetを書き換えているけど、独自拡張した、

Zend_Db_Table::join(Zend_Db_Table $joinTable, $joinType = 'inner')

というメソッドを使わない限りは、従来の各クラスとの互換性があるはず。

上記リンク先にサンプルコードとか制限とかいろいろ載せているけど、要は、

create table product(
id integer primary key auto increment,
name varchar(100),
);
create table stock(
id integer primary key auto increment,
product_id integer unique,
amount integer,
);

みたいなテーブルがあった場合、

$productTable = new Product();
$productTable->join(new Stock());
$products = $productTable->fetchAll('stock.amount < 5'); // 在庫が5より少ない商品を取得
foreach ($products as $product) {
$stock = $product->stock;
$stock->amount += 5;
$stock->save();
echo '商品' . $product->name . 'の在庫を' . $stock->amount . 'に増やしました。';
}

みたいな書き方ができるようになる感じね。

ただ実際にjoin機能を作ってみて分かったけど、こういうものを汎用的に使えるようにする設計は難しいね。

今回は割り切って、規約通りのテーブル定義以外では動かないようにしたから実装がシンプルになったけど、どのくらいイレギュラー(規約外)な場合を許容しつつ、その場合の対応をどれだけスマートに記述できるようにするか、ってのを考えはじめると、いつまで経っても設計が終わらない。っつーか、最初ちょっとくらいイレギュラーな場合にも対応できるようにしようと思ってたんだけど、中途半端にしかならないんであきらめた。

ごついjoin定義情報を背後に持っておいて、それを使ってjoinに関するイレギュラーなパターンを解決するというのが、真っ先に思いつく方法ではあるけれども、それって結局は単なる力業だし、そういう実装方法をそのまま表にまで出しちゃうと、利用者側レベルでの使い勝手もjoin定義情報と同じだけ複雑になりうることになっちゃって、あんまりスマートじゃないよなー。かといって、ごついjoin定義情報を利用者レベルでスマートに設定できるインターフェースってのも、なかなか設計が難しい。

俺としては、利用者レベルの使い勝手は今回の俺の実装程度のシンプルさで済みつつも、これよりももっと融通を利かせられるような本家実装を望むところ。

Published At2006-03-30 00:00Updated At2006-03-30 00:00

日記
なぜCSSXSSに抜本的に対策をとることが難しいかEdit

CSSXSSの説明について、その脅威を過剰に表現している部分がありました。その部分について加筆訂正しています。 @ 2006/4/3

tociyukiさんによる「[web]MSIE の CSSXSS 脆弱性とは何か」および「[web]開発者サイドでの CSSXSS 脆弱性対策」には、より正確なCSSXSS脆弱性の内容およびそれに対するサーバーサイド開発者で可能な対策について紹介されていますので、是非そちらもご覧ください。 @ 2006/4/4


今までも何度かこの辺の話はあまり具体的ではなく書いてきたけど、そろそろCSSXSSを悪用したい人には十分情報が行き渡っただろうし、具体的な話を書いてもこれ以上危険が増すということはないだろうから、ちょっと具体的に書いてみる。

ちなみに私自身は、CSSXSSの攻撃コードなどを実際に試したりといった調査は行っておらず、信頼できそうな他者の公開情報を組み合わせて理解しているだけなので、事実誤認等が混ざっているかもしれない。指摘があれば適宜修正する。

まずCSSXSSというのは、現在のIE(Windowsのみ?)が持つセキュリティホールである(とはっきり書いておこう。その他のブラウザで同様の問題が起きるという話は聞かない)。具体的な内容としては、

<link rel=stylesheet href="[URL]" type="text/css" />

などの方法で、(X)HTMLドキュメントから[URL]で指定された外部スタイルシートを参照すると、そのURLから返された内容がスタイルシートではなく、通常の(X)HTMLドキュメントであったとしても、JavaScript(などのIEが持つ拡張機能)を使ってその内容を取得することができる。

ただし、あらゆるドキュメントが取得できるわけではなく、その内容がある程度スタイルシート定義テキストに似ている(文字要素としてスタイルシート定義で使われる記号が含まれる、など)必要があるようだ。しかし、その細かい条件については定かではない。

ただし、単純にドキュメントの内容すべてを取得できるという訳ではなく、ドキュメント中のスタイルシート定義に似た一部分のみが参照できるようだ。tociyuki氏のご指摘を元に、私が試してみた範囲では、通常はHTML中に含まれるCSS定義部分のみが参照でき、CSS定義以外のドキュメントは参照できない。ただし、ドキュメント中にIEからはCSS定義のように見える部分を作り出すことによって、CSS定義以外のドキュメント要素も参照可能にすることができるようだ。そのあたりの具体的な条件については、実験によってある程度は解析できるが、確実な条件は設定できない(=プログラムロジックで判別できない)。

また、上記linkで指定されたURLの内容をブラウザが取得しに行く際には、その時点でそのURL(ドメイン)に対してブラウザ(=閲覧者)が持つ権限が利用される。

たとえば、そのURLにアクセスするためには本来ログインが必要な場合でも、そのブラウザがそのURLで提供されるサービスにおいて、ログイン済みの状態になっているのならば、たとえ他サイト(サービス)上の本来認証しないとみられないはずの情報にも、アクセスすることができる。

具体的には、もしアクセス者がmixiやはてなにログイン済みだった場合、http://free.example.com/cssxss.htmlなどに設置された攻撃コードから、http://mixi.jp/home.plhttp://www.hatena.ne.jp/などにアクセスすることで、各サービスにそのアクセス者が認証状態のときに表示されるページを構成するHTMLが取得でき、そこに表示された情報(たとえばアカウント名やプロフィール情報など)を読み取ることができる(本当に上記URLにCSSXSSアクセス可能かどうかは未確認通常は単にアクセスしただけでHTMLドキュメント中の情報が盗まれることはないだろう。ただし前記のような条件が整う(攻撃者によって整えられる)ことによって、CSS経由でHTMLドキュメント中の情報を外部から参照することが可能になる)。

これだけでも大問題なのだが、さらに問題なのがCSRF攻撃と組み合わせた場合だ。

CSRF(Web上のサービスで提供されている機能を、他人の権限で操作する攻撃)に対する一般的な対策は、ある程度重要な機能を実行する前の認証チェックは、Cookieのようにアクセスしたら自動的にブラウザから送信される情報だけで行わず、フォームのhiddenフィールドなどを使って「攻撃者が知りえない」&「アクセスしただけで自動送信されない」認証情報を付与し、二重に認証チェックすることによって、攻撃を防ぐ方法だ。

ほかにも対策はあるが、この方法は利用者のユーザビリティをほとんど下げることなく、CSRF対策が行える。

しかしCSSXSSをつかえば、CSRF対策のためにフォームのhiddenフィールドなどにセットしたもう一つの認証情報を、攻撃者が盗むことが可能になる。そして、それを利用して外部サイトからCSRF攻撃を成功することが可能になる。

というように非常に重大な問題でありながらも、もう数カ月も修正されずにマイクロソフトによって放置されているCSSXSSだが、ブラウザ側の修正を待たずにサーバー側で対策を行うことは可能だろうか。

その答えとしては、ある特定された状況における問題を回避するように修正することは可能であろう。しかし、CSSXSSという問題に対して、抜本的な対策をサーバーサイドのみで行うことは、現在のWebアプリケーションの設計手法を根本から変えない限りは、不可能だ。

まず、CSSXSSの根本的な問題は、他サイトの認証済みページに表示される情報を盗むことが可能である、という点だ。これを回避する方法としては、上記までの(私が知りうる限りの)情報から考えるに、

  1. 認証済みページに表示する内容は、CSSXSSでは読み取れない内容(文字構成)にする
  2. 外部スタイルシート(として指定されたURLのドキュメント)の取得は必ずGETアクセスで行われるので、認証済みページの重要な情報はすべてPOSTアクセスでないと表示されないようにする

となる。それぞれについて検討してみよう。

最初の条件については、そこに表示される内容が静的なドキュメントならば、対策は可能だろう。実際にIEでCSSXSSアクセスを試みて取得できなければ、それはCSSXSSでは読み取れない内容であるということになる。ただし、そのドキュメントを作成する際の制限およびチェックコストはとても大きい。

一方、動的なドキュメントを生成するようなWebアプリケーションでは、その内容をCSSXSSでは読み取れないようにすることは可能だろうか? 動的なドキュメントを生成するWebアプリケーションでは、そのコンテンツが変化していくものだ。コンテンツが変化するたびに、実際にCSSXSSで読み取られることがないかをチェックすることは可能だろうか? 現実的は不可能だろう。

続いて、認証済みページはPOSTアクセスでのみ情報を表示するようにする、という条件について考えてみる。つまり、認証済みページ内でのページ遷移は単なるリンク(GETアクセス)は許されず、必ずform method="post"を使ったsubmitにする必要がある。

こちらは最初からそういう設計で構築する分には、実現は不可能ではない。しかし、従来の(通常の)Webアプリケーションに関する常識のもとに設計されているサイトを、すべてそのように変更するのは非常に大変だ。また、利用者から見ても、認証済みページのページ遷移がすべてPOSTアクセス(form submit)となると、ユーザビリティは大幅に低下することだろう(たとえばはてなダイアリーで、ログイン後はすべてのリンクがsubmitボタンになると思いねぇ)。

ちなみに、内部的にはすべてPOSTアクセスが行われるが、一般ユーザーレベルの使い勝手はリンク(a href)をクリックするのと変わらないような仕組みを、JavaScriptを駆使して実現することは可能だ。たとえばマイクロソフトのASP.NET(+VisualStudio)でWebフォーム+サーバーコントロールを使えば、単なるリンクも内部的にはPOSTアクセスとして実行される(ここで、実はマイクロソフトがASP.NETを広めるためにCSSXSS対策を行わないのだ、という陰謀論を10行割愛)。

また、認証済みページにおける情報は、すべてAjax(XmlHttpRequest+POST)を使って取得&表示するようにしても、CSSXSSで盗まれることはないだろう(外部スタイルシートを読み取る際に、そのドキュメント上のJavaScriptが実行されたりはしない)。

どちらにしろ、これらの対策は従来のWebアプリケーション設計手法とは異なる方法でWebサイト(アプリケーション)を再構築する必要があり、またブラウザ互換性も損ねてしまう。あるいはブラウザ互換性の代わりにユーザビリティを大幅に下げることになる。

もちろん現時点で、非常に重要な機能・情報をCSSXSSから保護するために、上記のような対策を取ることは必要だろう。しかし、CSSXSSがないことを前提として設計したサイトを、抜本的にCSSXSSフリーにするためには、単に部分的な修正ではなく、サイト全体の再構築を伴うこととなる。

ちなみにCSSXSSを利用したCSRFに対してのみ対策を行うとなると、ある程度は実現可能になってくる。CSRF対策に関係するページは数が限られるので、それらをすべてPOSTアクセスのみに変更することは、現実的に対応可能だろう。

ただし、従来の(CSSXSS対策を考えない)設計とは使い勝手が変わってくるし、場合によってユーザビリティが低下する(従来は不要だったPOSTアクセスが1段階必要になることがある)。つまり、CSSXSSのためのセキュリティ的な改善=ユーザビリティ的な改悪を伴う可能性が高い。そうなると、IE側でCSSXSS対策が行われたあとには、(従来のユーザビリティに戻すために)もう一度全体のデザインを調整する必要が出てくるだろう。

最終的にサーバー側でどう対応するかは、危険性・実害・対応コストあたりの兼ね合いで決まってくるだろうが、その対応コストの見積もりには、単に修正する際の見積もりだけでなく、IE側の対応が終わった後に再修正が必要となる分も含めておくべきだろう。

Published At2006-03-31 00:00Updated At2006-03-31 00:00