2011年8月27日(土曜日)
ひだまりスケッチ6
公開: 2011年8月31日1時50分頃
6巻が出ました。
- ひだまりスケッチ6 (www.amazon.co.jp)
相変わらず面白いですが、爆発的な面白さと言うよりもしんみりとした面白さというか。
まず印象に残ったのは「金属素材の円柱」。いかにもという感じで面白いですが、興味深いのは、タイトルによって見る人の見方が変わりそうだということ。採用(?)された「映り込む世界」というタイトルだったとすると、見る人は曲面に映る景色や、その表面のなめらかさといったところに注目することになると思います。それはそれで良いのですが、そうすると円柱の大きさ、重量感、といったその他の要素からは目を逸らされてしまうことにもなります。作者は、そのように見方を縛ってしまうことを嫌い、それで無機質な名前をつけたのではないかな、と思いました。
あとはラスト付近のエピソード。吉野屋先生が力強く見抜きつつも、その後ちょっと後悔して涙目になっていたりとか。最近、吉野屋先生がすごく良いなぁと思えるエピソードが多いように感じます。すごく一生懸命に美術の面白さやものづくりの楽しさを教えようとしたりしていて。まあ、変な先生ではあるのですが (6巻でも下半身ブルマのままで出かけようとしたり)、それさえも「芸術とは何か」ということを考えさせるためにあえてやっているのかも、と思えてきます (たぶん考えすぎ)。
- 「ひだまりスケッチ6」にコメントを書く
RangeつきリクエストによるApacheのDoSとApache Killerの実力
公開: 2011年8月30日1時45分頃
ApacheのDoSの脆弱性が話題になっていますね。
HTTP/1.1では、HTTP要求ヘッダでRangeフィールドを指定すると、コンテンツの全てではなく一部分だけを要求することができます。たとえば、以下のように指定するとデータの先頭の1バイトだけを受け取ることが期待されます。
Range: bytes=0-0
※これは以前にも書いたのですが、0-0で1バイト受け取るというのは微妙に直感的ではない感じがしますね。しかし正しい挙動です。
WebサーバがRangeを解釈した場合、ステータスコード 206 (Partial Content) で応答しつつ、指定された部分だけを返します。
と、これだけならRangeがない場合とサーバの負荷はほとんど変わらないのですが、実は1回のリクエストで複数の範囲を指定することができます。その場合、応答は Content-Type: multipart/byteranges となって、1回の応答で全ての範囲が返ります。RFC2616の19.2には以下のような例が出ています。
HTTP/1.1 206 Partial Content
Date: Wed, 15 Nov 1995 06:25:24 GMT
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT
Content-type: multipart/byteranges; boundary=THIS_STRING_SEPARATES
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 500-999/8000
...the first range...
--THIS_STRING_SEPARATES
Content-type: application/pdf
Content-range: bytes 7000-7999/8000
...the second range
--THIS_STRING_SEPARATES--
指定される範囲の数が増えると、パートの数が増えていくわけです。
さらに興味深いことに、範囲は重なっていても良いことになっています。RFC2616の14.35.1には以下のような例が出ています。
- Several legal but not canonical specifications of the second 500
bytes (byte offsets 500-999, inclusive):
bytes=500-600,601-999
bytes=500-700,601-999
bytes=500-700,601-999 という指定が可能だという点に注目してください。これはRFCにはっきり例示されている、れっきとした仕様です。
ただし、引用した例の前に "not canonical" と書いてあることにも注意が必要です。bytes=500-700,601-999 のような指定は冗長な書き方で、bytes=500-999 を指定したのと同様だと解釈されることが期待されます。
しかしApacheの実装ではそうなっていないようで、このような冗長な指定をまとめずに個々に処理してしまうようです。それを利用したのが今回の問題で、攻撃ツール「Apache Killer」は以下のようなRangeを送ってきます。
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,
(~中略~)
5-1293,5-1294,5-1295,5-1296,5-1297,5-1298,5-1299
これも本来であれば一つにまとめられて Range: bytes=0- と解釈されるべきですが、Apacheは律儀に大量のパートを生成しようとして、大量のメモリを消費してしまいます。
ところでこの攻撃、威力があるという話とそうでもないという話が両方出ているようです。良く分からないなあと思っていましたが、徳丸さんがその原因を調査されていました。
- Apache killerは危険~Apache killerを評価する上での注意~ (blog.tokumaru.org)
結論を簡単にまとめると、以下のようになります。
- Apache KillerのRangeは-1299までの指定なので、攻撃対象のコンテンツが1,300bytes未満の場合には攻撃の効果が薄くなる
- MaxClientsが小さな値に設定されていると、同時アクセス数が少なくなるため攻撃の効果が薄くなる
このため、テストのために暫定的に作ったような環境では、効果が薄くなる場合があります。逆に、きちんとコンテンツが置かれ、しっかりパフォーマンスチューニングされた環境は攻撃に弱いということになります。つまり、テスト環境は攻撃に強いが本番環境は攻撃に弱いということになりがちです。
ということで、油断しないで対応を考えた方が良さそうですね。
根本的なApacheの修正としては、RFC2616で期待されているように、冗長な指定は正規化して複数区間をできるだけまとめるという対応が望ましいでしょう。それでも歯抜けの細切れを指定されればバウンダリの分だけレスポンスのサイズは増えますが、組み合わせ爆発的な増加は避けることができるはずです。
暫定的な対応としては、Rangeを無視してしまうという方法も考えられます。RFC2616 14.35.2 には以下のようにあり、
A server MAY ignore the Range header.
WebサーバはRangeを無視する可能性があるということになっていますので、仕様的には問題ありません (ダウンロード中断・再開ができなくなって残念な思いをする人が出る可能性はありますが)。
- 前(古い): 2011年8月26日(Friday)のえび日記
- 次(新しい): 2011年8月28日(Sunday)のえび日記