hnwの日記

『体系的に学ぶ 安全なWebアプリケーションの作り方』のススメ


(2011/03/04 14:00 追記)id:shin1x1さんのはてブコメントに基づきheader関数の挙動について修正しました。ご指摘ありがとうございました。


徳丸浩さん(id:ockeghem)が書かれたセキュリティ本『体系的に学ぶ 安全なWebアプリケーションの作り方』が3/1に発売されました。この本はPHPのサンプルコードがふんだんに提示されているセキュリティの解説書で、セキュリティの理解を深めたいWeb技術者全員にお勧めしたい本です。



僕はこの本のレビュアーとして参加させて頂きましたが、他のレビュアーの方々が豪華メンバーすぎてまず驚きました。レビュアーMLの議論もハイレベルで、これをまとめたらそれはそれで売れるんじゃないか、というくらいのものでした。


他の方のブログでも絶賛されている中ではありますが、この本で僕が特徴的だと思う点を3点紹介します。

同一生成元ポリシーに関する記述

Webのセキュリティを担保している根拠の一つが同一生成元ポリシー(Same Origin Policy)だということは、セキュリティに詳しい人なら当然の前提といってもいいでしょう。一方で、セキュリティの本でもこの話題をとりあげないことが多いという印象があります。説明しにくい話題である上に、説明しなくても一通りの話はできるということなのかもしれません。


しかし、この本では「受動的攻撃と同一生成元ポリシー」として12ページを割いて説明しています。僕はこれを目次案で見たときから非常に楽しみにしていました*1。徳丸さんの「テクニックでなく本質を伝えたい」という気持ちの表れなんじゃないかと想像しています。

レインボーテーブルに関する記述

ハッシュ値の安全性に関する議論で、レインボーテーブルの仕組みについて記述があるのも面白いと感じました。ざっくり説明すると、短い文字列に対するハッシュ値の辞書を現実的なサイズで作る方法があり、一部はネット上で誰でも使える状態になっています。ですから、セキュリティ上の理由でハッシュ関数を利用する場合、短すぎる値を元にしてはいけません。


この話題も、セキュリティ界隈の人は全員知っているけど一般のWeb技術者はあまり知らない話題といえるかもしれません。ただ、ハッシュ関数をどう使うのか、ハッシュ関数で何が守れて何が守れないのか、といったことを知らずにハッシュ関数を使うのは危険です。


防御側の立場からすると具体的な攻撃方法までは知らなくてもいいかもしれませんが、レインボーテーブルのサイズ圧縮の理屈自体が面白いので、知っておいて損は無いと思います。

未知のバグに関する記述

この本の205ページに、PHPのheader関数はHTTPレスポンス分割攻撃に対する対策が完璧でない、という記述があります。


header関数は0x0A(\n)を含んだ文字列をレスポンスヘッダとして出力しようとすると、そのヘッダ全体を出力しない仕様になっています。しかし、今の実装では0x0D(\r)を素通ししてしまうのが問題だと指摘されています*2。というのも、IEChromeOperaの3ブラウザはレスポンスヘッダ中の0x0Dを改行とみなすため、現状のheader関数の実装ではHTTPレスポンス分割攻撃が成立してしまうというのです。


PHPを利用している大半の人がheader関数は安全だと考えていたのではないでしょうか。僕もこれには少しびっくりしました。僕が知らなかっただけならいいんですが、おそらく未知のバグだと思うので、bugs.php.netに報告したいと考えています*3

まとめ


僕が個人的に衝撃を受けた箇所を紹介してみました。この本の凄さは網羅性、徹底性といった部分にあると思いますので、少し偏った紹介をしてしまった気がします。その凄みの一部でも伝わるといいのですが…。


まあ、僕が改めて言うまでもなく、この本はWeb技術者必携のセキュリティ本だと思います。これからWebセキュリティを学びたいという人には敷居が高いかもしれませんが、1周目で全部わからなくても気にする必要はありません。むしろ、ときどき読み返すたびに新たな知見があるような本だと思いますので、意欲的な人は是非買っておくべきでしょう。


レビュアーとしても勉強になることがたくさんありました。徳丸さん、ありがとうございました。すでに好評のようですし、増刷がかかるといいですね!

*1:当初の目次案には含まれていなかったのですが、レビュアーの方からの意見を取り入れて作り直した目次案で追加されたものです。非常に書きにくい内容だと想像していたので、書くことにしたのは英断だと思っていました

*2:僕もPHPソースコードを確認しましたが、確かにそのような実装になっています

*3:既に報告済みのようでしたが、改めて報告しておきました