「出力」のセキュリティホール
「mixi非公開日記の画像を外部に晒す」に関して、一つだけ補足的に一般論を書いておきます。
エラーメッセージに余分な情報を込めるとクラックの糸口にされる
これは、まぁ、普通に正しい話だと思います。エラーはエラーであれば良く、わざわざエラーの詳しい理由を教える必要は全くない。極端なことを言えば、パスワードが間違っている場合は「ログインできません」とのみ表示すれば良く、「パスワードが●文字違ってます」などと教える必要は全くない(それはパスワードクラックしか誘発しない)。この延長線上として、mixiの非公開日記に関する仕様は非常に甘かった。で、まぁ、それは前提として、もう一つ同じような、今回の件で実は僕が一番「あああ・・・」と思った点に関する話を。
mixiの画像本体アドレスは
(画像ごとに固定された画像用サーバー).mixi.jp/p/(画像ごとに固定されておらず時間によって変化するランダムな文字列)/(時間と共に増えていく数字)/diary/(画像ごとに固定された数字)/(画像ごとに固定された数字)/(日記ID)_(画像を特定する数字).jpg
であり、つまるところ、これを単純なアドレスにすると外部からのブルートフォースに耐えられないので複雑化させてる訳ですが、はっきり言うと、ここに「日記ID」を含ませていることが、mixi管理サイドの決定的なセンス不足だ。
情報は、「繋がり」を持っている。プログラミングをよく知らない人向けに書いてみると
画像ID●●●はユーザーID●●●の日記ID●●●に含まれる
この、繋がり。これは基本的にはサーバーの内部プログラムで持たせるべき「繋がり」であり、まぁ「データベース」という言い方でいいか、データベース内で繋がりが定義されている。「内部」であるが故に、外部の人間、というか管理側以外の人間は、通常「繋がり」を知ることができない。
もし、画像本体のアドレスが
(画像ごとに固定された画像用サーバー).mixi.jp/p/(画像ごとに固定されておらず時間によって変化するランダムな文字列)/(時間と共に増えていく数字)/diary/(画像ごとに固定された数字)/(画像ごとに固定された数字)/(画像を特定する数字).jpg
であったらどうか。
- ブルートフォースに耐えるための情報量が下がるのでセキュリティ的に好ましくない
- 他の情報(日記ID)と「繋がる」情報が減るのでセキュリティ的に好ましい
おそらく、mixi管理サイドは前者の考えで画像本体アドレスに「日記ID」を含ませている。それが、明確に、センス不足だ。別に「この(特定の)攻撃を受けることを想定して〜」なんてことは言ってない。「何となく組んでみたプログラム」だったとしても、その出力に余分な情報(画像を特定するために、少なくとも日記IDは不要だ)を含ませているというセンス、の問題。ブルートフォースへの耐性を高めたいなら
画像ごとに固定されておらず時間によって変化するランダムな文字列
の桁数を増やすだけで、何故いけないんだ?
クラックとは、すべからく、「覗けない内部を推測するために外部から入力を行い出力を検証する」という行為に過ぎない。ここらへんに関して書いたのが「初級CGIクラックガイド」で、まぁ、なんていうか、2004年にMT化する以前に書き終わったコンテンツだったんだけどMT化後に途中までしかアップしてないことに今気付いた(年末年始にでも残りを再アップしますorz)。
「わざわざ」、画像本体アドレスとして、内部情報であるべき情報の繋がり(その画像が含まれている日記の日記ID)を出力する必要は、全く、無い。内部プログラムは情報を簡単に参照し、情報同士を簡単に繋げることができるが、それは基本的に外部から見えない。外部から見えるのは「自分が行った入力」と「出力」だけであり、情報とは、極論すれば全て、内部にのみ存在し、内部でのみ繋がっているべき存在だ(だからこそクラッカーは様々な工夫をこらし知恵を振り絞って「入力」「出力」から「内部の情報/内部での情報の繋がり」を探ろうとする、にも関わらずmixiの画像本体アドレスは「わざわざ」繋がりを教えてくれている)。
最初に話を戻すと、そもそも、「エラーメッセージ」も出力であり、「エラーメッセージを出力する」という事自体が
- 正しい→なんか上手くいく
- 間違っている→エラーメッセージ
と教える行為である、とも言える。パスワードZIPってありますが、あれのセキュリティを更に高めるなら、パスワードが間違っていても解凍できるべきです。ただ、解凍しても正しいファイルが生成されない、と。・・・この例はあんま上手くないが、極端なことを言えばそういうことだ。それが現実的に不可能だから、現実的に実現できる最大限のセキュリティとして、
- 正しい→解凍できる
- 間違っている→エラーメッセージ
という形で出力を行わせているのが、「パスワードZIP」だ(故にあれはマジでブルートフォース以外の方法では破れない訳で)。
「日記ID」と「その日記を書いたユーザーのユーザーID」を繋げるのに僕は若干苦労した訳ですが、それ以前に「画像本体アドレス」と「その画像が含まれる日記の日記ID」は普通に(「アドレス内に普通に含まれている」という理由で)繋がっていた。そういうシステムを作ることこそが、ウェブサービスにとって非常に大きなセキュリティホールだ。と、僕は、思う(もちろん「多少苦労しただけで繋がってしまう」日記IDとユーザーIDも問題なんだけど、それ以前の問題として)。

TrackBack
この記事へのトラックバック