水無月ばけらのえび日記

bakera.jp > 水無月ばけらのえび日記 > 2011年のえび日記 > 2011年8月 > 2011年8月27日(土曜日)

2011年8月27日(土曜日)

ひだまりスケッチ6

公開: 2011年8月31日1時50分頃

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 19.2 Internet Media Type multipart/byteranges より

指定される範囲の数が増えると、パートの数が増えていくわけです。

さらに興味深いことに、範囲は重なっていても良いことになっています。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

以上、RFC2616 14.35.1 Byte Ranges より

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の修正としては、RFC2616で期待されているように、冗長な指定は正規化して複数区間をできるだけまとめるという対応が望ましいでしょう。それでも歯抜けの細切れを指定されればバウンダリの分だけレスポンスのサイズは増えますが、組み合わせ爆発的な増加は避けることができるはずです。

暫定的な対応としては、Rangeを無視してしまうという方法も考えられます。RFC2616 14.35.2 には以下のようにあり、

A server MAY ignore the Range header.

以上、RFC2616 14.35.2 Range Retrieval Requests より

WebサーバはRangeを無視する可能性があるということになっていますので、仕様的には問題ありません (ダウンロード中断・再開ができなくなって残念な思いをする人が出る可能性はありますが)。

関連する話題: Web / セキュリティ / Apache / HTTP

最近の日記

関わった本など