0 / 5
ネットワークファイルシステム(NFS、Network File System)
NFS は、別のコンピューター(サーバー)のディレクトリを、自分のコンピューター(クライアント)のフォルダのように使えるようにするプロトコルである。ファイルはサーバーのディスクにあり、クライアントは読み取りと書き込みのリクエストをネットワークで送る。プログラムはローカルファイルを開くときと同じようにファイルを開く。
例: 会社のサーバーの /data フォルダを自分のコンピューターの /mnt/data フォルダにマウントして、サーバーにある a.txt を開く。
サーバーの答え: exports に書かれたホストのリクエストを処理する。
1 / 5
サーバー: 共有するディレクトリをエクスポートする
サーバーの管理者が exports 設定に、共有するディレクトリ /data と、アクセスを許可するクライアント 192.168.0.10 を書く。クライアントは、こうしてエクスポート(export)されたディレクトリだけを使える。
2 / 5
クライアント: サーバーのディレクトリをマウントする
クライアントがサーバーの /data を自分のフォルダ /mnt/data にマウント(mount)する。サーバーは、リクエストしたホストが exports に書かれているかを確認して許可する。マウントが終わると /mnt/data はサーバーの /data を指す。
3 / 5
プログラム: /mnt/data/a.txt を開く
プログラムは /mnt/data/a.txt を開くだけである。OS はこのパスが NFS でつながった場所だと見分け、ローカルディスクの代わりに NFS クライアントへファイル要求を渡す。
4 / 5
NFSクライアントからサーバーへ: 読み取り要求を送る
NFS クライアントが読み取り要求を RPC(リモートプロシージャコール)にしてサーバーへ送る。RPC は、別のコンピューターにある機能を呼び出す方式である。サーバーの NFS サービスは 2049 番ポートでこの要求を受ける。
5 / 5
サーバーからクライアントへ: ファイルの内容を返す
サーバーが自分のディスクから /data/a.txt を読み、内容を応答として返す。プログラムは、ローカルファイルを読んだときと同じように内容を受け取る。書き込み要求も同じ道を通る。そのときはサーバーのディスクのファイルが変わる。
1 / 5
サーバー: 誰にでも開いている設定
exports の * はすべてのホストを意味する。rw は読み取りと書き込みの両方を許可する。no_root_squash は、クライアントの root のリクエストをサーバー側でも root として処理させる。no_root_squash を使わなければ、既定の root_squash が適用される。
2 / 5
攻撃者: サーバーのディレクトリをマウントする
攻撃者が自分のコンピューターで、サーバーの /data を /mnt/data にマウントする。exports が * なので、攻撃者のホストも許可の対象に入る。
3 / 5
攻撃者: root でファイルに書き込む
攻撃者が root(UID 0)として /mnt/data/a.txt に書き込む。自分のコンピューターの root なので、クライアント側には止める仕組みがない。
4 / 5
NFSクライアントからサーバーへ: 書き込み要求を送る
書き込み要求が、ユーザー番号 0 とともに RPC でサーバーへ届く。AUTH_SYS では、サーバーはこの番号が本当に root のものか確かめる方法がない。
5 / 5
サーバー: UID 0 を信じてそのまま処理する
サーバーは、送られてきたユーザー番号 0 をサーバーの root として受け入れる。no_root_squash なので権限も下げない。その結果、サーバーのディスクの a.txt が攻撃者の書いた内容に変わる。
1 / 4
サーバー: ホスト・書き込み・root の権限を制限する
192.168.0.10 だけを書くので、ほかのホストはマウントできない。ro は読み取りだけを許可する。root_squash は、クライアントの root のリクエストを一般のユーザー番号(既定値 65534、nobody)に変えて処理する。
2 / 4
許可されていないホスト: マウントを拒否する
攻撃者のホスト(192.168.0.99)は exports にない。サーバーがマウント要求を拒否するので、攻撃者は /data を見られない。
3 / 4
許可されたホスト: 書き込み要求を拒否する
許可されたホストも /data には書き込めない。サーバーは書き込み要求を受けると、ro の設定を見て拒否する。
4 / 4
許可されたホストの root: 権限が下がって拒否される
root が secret.txt を読もうとすると、リクエストはユーザー番号 0 で届く。root_squash がこの番号を 65534 に変える。secret.txt は root だけが読めるので、サーバーは拒否する。クライアントの root がサーバーの root になることはない。ただし、root 以外のユーザー番号で送られたリクエストは、この設定では止められない。
1 / 3
サーバー: nfsd、statd、lockd を止める
NFS を処理するデーモン(バックグラウンドで動くサービス)を止める。nfsd はファイル要求を処理する。statd は相手コンピューターの再起動を見つけてロックを復旧し、lockd はファイルロックの要求を処理する。v3 のサーバーにはマウントを担当する mountd と、ポートを案内する rpcbind もあるので、これらもあわせて確認する。
2 / 3
認可されていないシステムのアクセスを断つ
サーバーの管理者が exports から認可されていないホストを外して、アクセスを防ぐ。そのシステムに残ったマウントは、そのシステムで umount して片付ける。サービスを止めることとは別に、すでにつながっているシステムを整理する対策である。
3 / 3
攻撃者のリクエスト: 受けてくれるサービスがない
攻撃者がもう一度ファイルを読もうとしても、2049 番ポートに届くリクエストを受ける nfsd がない。サービスを止めれば、設定が甘くても攻撃が届く場所がない。