いつきコンテンツ

ヘルプ

カウンター


2007-10-29 実証できました。

前々から実証したいと思ってましたが、VMware上で実証できたので公開。

実証したのは昨日の日記で言っている、「mbox周りにバグ有り(リモートからmboxの内容を壊す事が出来る」って内容です。

[日記][Unix] というわけで、パッチ公開~

qmailでmbox形式でメールを保存すると、特定環境下で外部からメールが消されてしまうのの対策+DoS喰らいにくくするパッチ

数年前(ソース解析時だから、2000年頃?)から気づいていたけれど、実証がめんどくさくて放置していた、qmailでmbox形式で保存する時に運が悪いとメールが消えてしまう事に対するパッチです。
んで、実証の時に、効率良くmboxを破壊するために風呂場で思いついたDoSが本当に通ってしまったので、その対策パッチも合わせて公開します。

まず、「qmailでmbox形式でメールを保存すると、特定環境下で外部からメールが消されてしまう」事についてです。

問題が起きるケースは次の条件の時です。
・ファイルシステムが4G以上のファイルサイズを扱える
・32bit OSを使用。ただし、64bit OSでも、unsigned longが4byteの場合はアウト。

mbox形式のファイルが4Gを超えている状態で、qmail-localが(4Gを超えた)ファイルをいじっている時にエラーが起きると、ファイルが本来のサイズよりかなり小さくされてしまいます。
具体的には、オリジナルのqmail-local.cの204行目や225行目のseek_trunc(fd,pos);が実行されると問題が発生します。
何が起きているかというと、seek_posがseek.hにおいて、unsigned longと定義されている為、mboxのファイルサイズを記録している192行目あたりで(seek_pos posと定義されている)pos = seek_cur(fd);とやっちゃってる為、off_t(ファイルサイズを記録する為の型。ファイルシステムが4G以上のファイルを扱える場合は64bitである事が多い)をseek_posに代入、という処理が発生しています。
つまり、sizeof(seek_pos) = sizeof(unsigned long) < sizeof(off_t)となってしまい、posが32bitの表現限界を超えて0に戻ってしまうため、その後のエラー処理で元のサイズに戻そうとして、元のサイズの下位32bit分の大きさにしてしまうのです。このため、mboxの内容が消えるという現象が発生します。
ちなみに、Maildirを使っている時はseek_truncしないので、問題が顕在化しません。

この現象を起こすのに一番簡単な方法は、「qmail-localのヘッダ処理中にメモリ不足でエラーにする」コードです。これは(exploitコードを見てもらえば分かりますが)巨大なヘッダのメールを大量に投げると遠隔からでも簡単に発生することができます。
……と思ってましたが、エラーメッセージを見たら、「Unable_to_write_/usr/home/mail/Mailbox:_out_of_disk_space._(#4.3.0)」だそうで。確かにこっちの方がエラー起きやすい(笑)DoSすればいいんだから簡単だねぇ。

ちなみに、問題の根本は、unsigned longを0~∞の整数を扱えるごとく扱っている事です。そういえば、以前あったqmail-smtpdの2G超えの時にアクセス違反で落ちるのも同じ原因ですね(^^;
なので、類似のバグは他にも何かありそう。探すのがめんどくさいので今回はこれだけ。
何か気づいた人は実証してパッチを公開しましょう(笑)

mboxが壊れるのはFreeBSD 6.2 p8 + portsでデフォルトでインストールしたqmailで実証しました
パッチも、多分動きます(笑) 簡単なテストはしましたが、問題なさげなので。
ただし、一切の保証をしません。自己責任でどうぞ。


次、DoS喰らいにくくするパッチです。
これは上で書いた「qmailでmbox形式でメールを保存すると、特定環境下で外部からメールが消されてしまう」を起こすのに、4G以上のメールボックスが必要で、効率よく4G超えのメールボックスを作るために「qmailでは複数のrcpt toがあると、全部ばらして配信する」という特徴を使ってファイルサイズを巨大化させた時に、DoS状態になったため、それを回避する為のパッチです。

DoS状態になる理由は簡単で、受け取ったメール本文をrcpt toが入力された回数展開して配信する為です。
exploitコードでは、rcpt toを1024回、本文を1Mで4回送信(つまり、1024*1M*4=4G!の配信が行われる)という送信方法をとっています。(実際にはヘッダが付加されるため、もっと小さくてもexploitが可能なはずですが、安全係数取ってあります)
やっている事は簡単で、controlの中にmaxrcpttoというファイルに整数を書いておいておくと、その回数までしかrcpt toを受け取らなくなります。
常識的に考えて、10個も同時に来ないでしょうから、10とでも書いておけばかなりDoS状態になりにくくなります。

以上、qmailのパッチの説明でした。

おまけ:mbox-dos.pl.txt
ローカルのroot宛に大量にメールを送ります。perlがあれば、多分実行できます。
&mail_send_mbox()が4Gオーバーにさせるための部分で、&mail_send_mbox2()が、メモリ不足を誘発しやすいメールを送る部分です。
あとは自力で読んでください。

(c)2007 Copyright, Ituki Kirihara/NI, All rights reserved.

なお、本パッチ・expolitコードは使用、再配布、転載等、自由に行っていただいて結構ですが、出来るだけこのテキストも一緒に配布してください。と言うか、誰か英訳してくれ(笑)
著作権は放棄しませんが、よほど悪質なケースを除いて権利の行使をしません。

私のホームページ
http://fc.to/ituki/ or http://blog.proj.jp/ituki/
パッチ公開場所
http://fc.to/ituki/software/patch/

というわけで、mbox使ってる人は注意しましょう。間違ってたら指摘よろしく。→いきなり自分で間違い発見(笑)『……と思ってましたが、エラーメッセージを見たら、「Unable_to_write_/usr/home/mail/Mailbox: _out_of_disk_space._(#4.3.0)」だそうで。確かにこっちの方がエラー起きやすい(笑)DoSすればいいんだから簡単だねぇ。』ってのを追加。

exploitは、4G以上でそんなにでかくないディスクで実行してください。メモリ不足はOSがkillしていた(笑)

つか、qmail、DoS喰らいやすそうなー。

そういえば2chのqmailいろいろ(4)の337当たりに書き込んでたなー。2004年時点ですでにこの問題は発覚していたわけだが。

[ネタ][情報] 台風20号が接近! 秋葉原ダイビル周辺は傘破損率400パーセント!?

秋葉原ダイビルと秋葉原UDX周辺。この近辺は強いビル風が発生しており、ひどいときには神田明神通りを歩行する人の傘がほぼすべて破壊される

あー、言われてみれば確かに。

雨風の強い時は気をつけよう。

[情報] DNSサーバーは絶対に信頼できるのか

疑い出すときりがないですな。

ローカルでresolver立てる位しか回避策はない?(笑)

[ネタ] ニコニコから消されるアニメのDVDは買うべきじゃない

ちょっと面白かったので。

人気がある→アプされる、なのか、アプされる→人気が出る、なのかが分からないですね。もしかしたら、ループかもしれず。

それによって、良いところをついてるか、妙な事を言っているのかが変わりますな。

[メモ][情報] 正しいPerl/CGIの書き方

面白そうなのでメモっておく。

[メモ] ポルノコミックは規制されるべきか

というわけで、/.jp入り。

色んな意見が混じっていて面白いのでメモっておく。

[日記][Unix][メモ] mrtg設定メモ

index.htmlを作る

indexmaker --columns=1 mrtg.cfg > htdocs/index.html

smartmontoolsを使ってHDDの温度を取ってくる

/usr/local/sbin/smartctl -a /dev/HDDのデバイス | grep Temperature_Celsius | awk '{print $10}'

ただし、「/dev/HDDのデバイス」に読み書き権限が必要。従って、root以外はsudoあたりを噛まして実行しないとエラーになる。

Last Update: 2007-10-29 23:59:29

カレンダー

2003|04|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|07|08|11|
2013|03|05|08|
2014|01|
2015|04|05|06|07|09|10|12|
2016|01|03|05|06|10|11|
2017|06|
2018|05|08|09|10|11|
2019|04|08|
Generated by tDiary version 4.1.2 + amazon(DB Patch 0.2.1) + counter(DB Patch 0.2) + IKPatch version beta 4.0.1.
Powered by Ruby version 2.1.5-p273 with ruby-fcgi