ホーム > GNU/Linux > NFSサーバのIPアドレス制限は割と簡単に回避できる

NFSサーバのIPアドレス制限は割と簡単に回避できる

NFSの仕様を理解していない方が多いようですが、NFSのマウント成功=NFS上にrootを除く任意のユーザとしてアクセス可能(デフォルト設定の場合。nosquashしていればrootでも素通りする)であるということです

kerberos使ってないNFSを特定条件下で外部から割と簡単にマウントできてしまった話です。

NFSのセキュリティ機構といえばkerberosですが、
この設定が難解で運用が難しく、/homeに使うにはsshの公開鍵認証との相性が悪い事もあり、
IPアドレスベースの制限で済ませている環境も多いかと思います。
IPアドレスベースで制限をかけ、ネットワーク的に独立していれば安全、そう思っていた時期が私にもありました・・・

想定するネットワークの構成は
[ファイルサーバS(NFS)] – SAN – [クライアントマシンC(一般ユーザがssh接続可能)] – 外部
という構成です。割とあるんじゃないでしょうか。
変なルーティングやアクセス制限の設定ミス、SANへの物理的接続による攻撃はないものとします。

さて、この環境下でCのユーザが外部からNFSサーバをマウントすることを考えます。
ssh接続可能というあたりで察した方も多いかも知れません。

【NFSをポートフォワーディングします】

NFSv4 over TCPの環境では非常に簡単です。NFSv4は2049/tcpで完結しているため、

ssh -L2049:S:2049 user@C

2049/tcpをポートフォワードすればそのままlocalhostに対してマウントが通るはずです。
通らなければ次に述べるNFSv3の方法を試すと通ると思います。
sshのポートフォワーディングが禁止されている場合にもnetcatを使えば良いのです。
要は、sshでシェルがとれる状況であれば回避できません。

NFSv4 over UDPの環境でも同様に、何らかのフォワーダを自作すれば通るはずです。
あるいは、sshのsocks機能を使うともっと簡単にできるらしいですが、私は未検証です。

NFSv3 over TCPの環境ではmountdのポートがダイナミックに変わるので若干ややこしくなります。
今回実際に攻略したのはこのパターンです。
まず、NFSの2049/tcpとrpc portmapperの111/tcpをローカルにポートフォワードしてきます。
ここで、ループバックインターフェイスに対してwiresharkを仕掛けておきます。
この状態でlocalhostに対してマウントをかけると、portmapperの応答パケットが見えます。
mountdのポートがわかるので、追加でポートフォワードするとmountコマンドからプロンプトが返ってきてマウント成功します。
sshのsocks機能とそれをtun仮想デバイスに変換するソフトがあるからもっと簡単にできるよって@nvsoftsが言ってた。

NFSv3 over UDPはめんどくさすぎるので未調査。socksで簡単にできるよって@nvsoftsが言ってた。
多分自力でフォワーダ書けばなんとでもなると思います。

ということで、NFSのIPアドレス制限は割と簡単に回避できてしまいます。
対策はNFSクライアント側でのみ実施可能です。前述のとおり、sshのポートフォワーディング禁止は役に立ちません。
根本的な対策としてはユーザランドプロセスからのdestport 2049を落っことすことです。
発見当初、そんな都合の良い方法はないだろうと思っていたのですが、ありました。
LinuxのiptablesとFreeBSDのpfには生成元プロセスのuidやgidに基づくフィルタリング機能があります。
ここではiptablesによる制限を紹介します。

iptablesにおいて、NFSのようにカーネルから発生するパケットはuid/gidではいずれの数値にもマッチしません。
また、!でnot演算すると必ずマッチします。

-A OUTPUT -m tcp -p tcp --dport 2049 -m owner --uid-owner 0:65535 #マッチしない
-A OUTPUT -m tcp -p tcp --dport 2049 -m owner ! --uid-owner 0:65535 #マッチする

ということで、こんなことを書けばとりあえず穴は塞がります。

-A OUTPUT -m tcp -p tcp --dport 2049 -m owner --uid-owner 0:65535 -j DROP
-A OUTPUT -m udp -p udp --dport 2049 -m owner --uid-owner 0:65535 -j DROP

もしかすると、NFSv3だと不具合があるかもしれません。
// そんなレガシーなプロトコルは手元の検証環境にないぜ!
redhat系だとrpcuserがそのへんをやっている可能性があるので、ピンポイントで通してやることで解決するんじゃないかと思います。
lockdはカーネル空間。rpc系プロセスはrootで動いてるのとrpcで動いてるのとrpcuserで動いてるのがいてわけがわからない。

ここからの応用で設定の甘いNFSクライアント(C)側を完全掌握する方法については次回。

— 2015/2/4 22:33 —
socks周り勘違いしていたので修正。sshのsocks機能でUDPを通せるか、さらにNFSを通せるかについて検証してくれる方募集。

— 2015/2/15 —
追試の結果、CentOS 6だとデフォルト設定では一般ユーザが開けるポートからのマウントはrefused mount request : illegal port 38058 とか出てきて落とされるようです。
これを解除するにはexportsにinsecureオプションをわざわざ指定する必要がある模様。発見した環境、なんでこんなもん設定されてたんですかね・・・

広告
カテゴリー:GNU/Linux
  1. まだコメントはありません。
  1. No trackbacks yet.

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。