デーモンプログラム内蔵のchroot()

最近Gentooのrsyncサーバが乗っ取られた。 これはrsync 2.5.6にバッファオーバフローを起こさせて落とした、というやつ だったが、これは rsync のコーディングの問題というよりも、 デーモンモードで動かすときのデフォルトの思想に問題がある。

デーモンモードで動かすとき、つまり、rsync --daemon するときは、rsyncd.conf に定義された配布ディレクトリ に chroot() して、配布ディレクトリ以外のファイルを破壊しないようにする、 という配慮がデフォルトでONになっている。これが災いした。

rsyncdはポート873で待ち受けするため、起動時にはroot(UID=0)でなければ ならない。さらに、その後でクライアントの接続を許し、リクエストに応じた 配布ディレクトリにchroot()するためには、クライアントのやりとりが始まって からしばらくはUID=0でいつづけなければならず、この間にバッファオーバフロー を狙われてそれが成功したら文句無しでrootを奪われてしまうことになる。

結局のところ、ネットワークサービスデーモンで、クライアントの接続をう けたあとでchroot()するようなプログラムは、どれもこれもその危険性を内在し ていることになる。「このプログラムは自動的にchroot()します」と書いてあっ たとした場合、chrootという言葉で無条件に安全だと判断してはいけない。

安全なのは、

を先に済ませてから即座にUID=0から脱却し別の一般ユーザIDにsetuidした のちに

もの。逆に、安全でないのは、

ものである。まさに rsync --daemon の デフォルトがこれで、これを回避するためには rsyncd.conf

use chroot = no

としておけば良い。ただし、これでも rsyncd の場合は不十分で、 ポート873に接続を受けて

最初のリクエストを受けるときはrootのまま動いている

という甘さがある。今回の事件が契機になって、rsyncがバッファオーバーフ ローを起こす可能性はほとんどなくなってはいるであろうが、 「ルートディレクトリでルートユーザのまま動いている」という古風な 状態が存在することには変わりない。

rsyncdに限らず、「1024未満の特権ポートを使うけれどもrootである必要の ないデーモンプログラム」はこのような順番で動かすべきだ。

  1. chrootが可能ならchrootする
  2. rootユーザのままポートをbind()させる
  3. 一般ユーザにsetuidさせる

これを汎用的に行なえるのが chroot コマンドと tcpserver の組み合わせで ある。tcpserverでは最初にroot権限でポートを確保したら即座に別UIDに移行 できるオプションがあるのでこれを利用する。まとめると、以下のような シェルスクリプトになる。

#!/bin/sh
exec env - \
PATH=/usr/local/bin:/usr/bin:/usr/sbin:/bin \
chroot /somewhere/to/chroot \
envuidgid nobody \
tcpserver -vR -c40 -U 0 rsync rsync --daemon --no-detach 2>&1

chroot空間 /somewhere/to/chroot 内の usr/local/bin など に rsync, envuidgid(daemontools) や tcpserver(ucspi-tcp) がインストール してあるものとする。--no-detach は daemontoolsのsupervise経由で起動する ためにつけてみた。

このようなコマンドの組み合わせで起動すると、ポート873で待ち受けを行な うプロセスは

USER       PID %CPU %MEM   VSZ  RSS TT  STAT STARTED       TIME COMMAND
nobody   65459  0.0  0.1   916  504  p5  I     3:36PM   0:00.02 tcpserver -vR -p -c40 -U 0 rsync rsync --daemon --no-detach

のように nobody 権限になる。よろしい。


Generated with mkdiary.rb
yuuji@example.org
Fingerprint16 = FF F9 FF CC E0 FE 5C F7 19 97 28 24 EC 5D 39 BA
HIROSE Yuuji - ASTROLOGY / BIKE / EPO / GUEST BOOK / YaTeX [Tweet]