IRC(Internet Reray Chat)には、DCCというファイル送受信や個人チャット用途に設けられた機能がある。Direct Crient-to-Crient という名前のとおり、IRCサーバを介しない通信に用いられる。これには、以下の2つの利点と目的がある。
- ファイル送受信など、大量のデータをやり取りする際、IRCサーバを経由するよりもクライアント同士が直接通信した方が転送効率が良い。また、サーバに負荷をかける事がない。
- IRCサーバは他人が管理している為、そこを経由した会話は絶対安全だという保証はない。クライアント同士が直接通信する事によって、ある程度のセキュリティを保つ事が出来る。
DCCは、ファイル送受信を例に挙げると、以下のような仕組みで実現されている。
- ファイルの送信元がIRCサーバを経由して、以下の情報(DCCファイル受信リクエスト)を送信先に伝達する。
送信元nick ファイル名 送信元IPアドレス:ポート番号 ファイルサイズ - リクエストを送信後、その情報どおりにファイル送信の待機状態(Listen)に入る。
- リクエストを受け取った送信先は、ユーザにその旨を通知し、ファイルを受信するか否かを決定してもらう。
- ファイルを受信する場合、送信先はリクエストの情報を元に通信経路を確立。ファイルを受信した後に切断する。
昨今のIRCクライアントは洗練されたものが多く、Windows Live メッセンジャーのようにサーバを経由しない為、快適にファイルを送受信する事が出来る。
さらにIRCプロトコルは非常にシンプルに出来ており、RFCなどを参考にIRCコマンドを直打ちすれば、telnetコマンドでもチャットに参加し会話する事が出来る。DCCも同様に、IPアドレスとポート番号が分かっているならば、telnetでも接続は可能なはず。
という事で以前、DCCの設定を行っていた際にこんな実験をしてみた。
telnet でファイル受信
上の表の2番までを行った状態で、シェルより以下のコマンドを実行する。
$ telnet 送信元IPアドレス ポート番号
すると、送信するファイルのデータが一気に流れてくる。プロトコルも何もない本当の生データが流れてくる。
送信するファイルをテキストにし、キャラクタセットを送信先のシェルに合わせれば、テキストファイルの中身がそのまま表示される事となる。
Windowsのコマンドプロンプトを例にすると、以下のとおり。
- ShiftJIS/CR+LF改行のテキストファイルを準備し、IRCクライアントから送信先にDCCファイル受信リクエストを送る。
- IRCクライアントは、接続待機状態に入る。
- 送信先に表示されたリクエストを参考に、送信先ホスト上で、コマンドプロンプトから上のコマンドを実行する。
- コマンドプロンプトにテキストファイルの情報が表示される。
ここであれっと思ったのは、IRCクライアント側がどうも実際に受信をしているホストをチェックしていない点だ。
リクエストを送っていない人が勝手に受信
実際に受信をしているホストをチェックしない、とはどういう事だろうか。
以下に分かりやすく、例を示す。
ファイルの送信元をAlice、送信先(つまり受信者)のBob、同じIRCサーバに居る第三者をEveとする。
- Alice「ねえBob、ファイルを送るから後で読んでね」
- AliceがBobに対して、テキストファイルを送ろうとして、DCCファイル受信リクエストを送った。
- ( Bobは離席しているようだ。一向に受信する様子はない。 )
- Alice「あれ、居ないのかな?」
- それを同じチャンネルで見ていたEveは、IRCサーバに問い合わせ、AliceのIPアドレスを調べた。
- Eve「AliceのIPアドレスは、XXX.XXX.XXX.XXXか。彼女は確かLimeChat2を使っていたはず。」
- Eve「LimeChat2のデフォルトのDCCファイル送信用ポート番号は1096~1195。ポート開放程度は出来ても、ネットワークには疎いあの子の事だからデフォルト値のままのはず。」
- Eve「さらに彼女のログイン時刻はつい数分前だから、ファイル送信にListenしているポートはきっと、1096ね。」
- そう呟いたEveは、シェルを起動し、「$ telnet XXX.XXX.XXX.XXX 1096」を実行した。
- Alice「あ、Bobがファイルを受信してくれたっ」
- シェルに映し出された赤裸々なメッセージ。Eveは一人ほくそ笑んだ。
- Eve「アラアラウフフ」
この場合、もちろんBobにはAliceのテキストファイルは届いていない。Eveが横取りをして、受信してしまったからだ。
検証したのはLimeChat2だけだが、現在のIRCクライアントのほとんどが、「DCCファイル受信リクエストを出した相手(本来の受信者)」と「ファイルの受信をしに来た相手(本来の受信者かどうか不明)」が同一であるかどうか、チェックしていないと思われる。つまり、リクエストを送信しListenした状態は、誰が接続して来ようがファイルを送信してしまうのだ。
Eveが本気で悪意を持った場合
上の例では、どこぞやのバーロー名探偵の事件のように希望的観測に基づいた推論が都合良く成立している。これではあまり現実味がないし、悪意がある側の効率だって悪い。Eveが本気で悪意を持った場合、次のようなツールを書くだろう。
- IRCサーバからターゲットのIPアドレスを取得。
- 効率を上げる為に、ターゲットに対してポートスキャンを実行。LimeChat2のようにある程度ポートの範囲が絞れている場合は、やらなくても可*1。
- DCC送信ポートを監視。接続可能になるまでくりかえす。
- コネクションが成立したら、あとは送信してきたデータを受信し、保存する*2。
このようなツールは、数時間もかからずに出来てしまいそう*3。上のやりとりの例のように手間暇をかけずとも、ツールを起動しておくだけでターゲットの送信ファイルを横取り出来るのだ。
横取りされたAliceにとって、彼女のクライアントには「Bobに対するDCCファイル送信が完了した」と表示され、Bobには「AliceがDCCファイル受信を要求している」という表示になっているまま。Eveに横取りされているとも知らず、戻ってきたBobが受信を開始しようとしてもエラーが起きて受信は出来ない。さらに、AliceやBobがDCC送信ポートの設定もやっとな知識のユーザであったら、「ポートの調子が悪いのかな」程度に思い、横取りされた事実さえ気が付かないかもしれない。
対策
LimeChat2には、DCCファイル受信リクエストが来たら自動的にファイルを受信する機能がある。もしも送信先がそのような設定になっていれば、ツールによる横取りも100%ではないがある程度防げると思う。ただし自動受信自体、セキュリティ的にはあまりオススメできる手段でも無い為、根本的な解決にはならないと思われる。
ホストチェックの仕組みは、RFCを弄らずとも各クライアントの対応でなんとかなりそうなので、各クライアントレベルでの対応が望ましい。
なお、今回検証はしていないが、DCCチャットも同じ事が言えるかもしれない。
以上、知っている人にとっては今更な情報かもしれないが、知らなさそうなユーザがたくさん居る事についての警鐘の意味も兼ねて、ここに記載した。
細かな事は知らなくてもいいと思うが、「横取りされ得る」という事実だけは、しっかりとユーザの間で認知されるべきではないだろうか。
ちなみに今回は、多くのWindowsユーザが利用しているLimeChat2を中心に検討を行ったが、LimeChat2が悪いソフトと言う訳ではない。むしろGUIクライアントとしては最高のものだと思っている。
*1:CTCPでクライアントの種類を取得可能な場合がある
*2:ファイルの種類は file filename
*3:while :;do nc -w 1 -o tmp XXX.XXX.XXX.XXX:1096; sleep 1; done
※ 2020/07/02 度重なるブログ移転・ブログシステムのアップデートにより崩れた記事を校正。