ルートがエスケープできないchrootを生成するためにLinuxのファイルシステム内でchdir("..")を使用する方法は?

ルートがエスケープできないchrootを生成するためにLinuxのファイルシステム内でchdir("..")を使用する方法は?

/var/mychootと同じファイルシステムにディレクトリがあり、プログラムを起動した/ため、プログラムはEUID 0で実行されます/var/mychroot/progsudo chroot /var/mychroot /prog

プログラムが実行されるとchdir("..") エスケープ技術その後、chrootを脱出して内部のすべてを見ることができます/。 (Linux 4.18でこれを確認しました。)

私はそのような脱出を防ぎたい。実際、私はさまざまなchrootエスケープを避けたいのですが、この質問では何をすべきかについてのみ興味があります。chdir("..") エスケープ技術これは、最新のLinuxシステムでは回避できます。そのために代替案を探しています。chroot(2)システムコール。

2つの解決策が見つかりました。ピボットルートそしてMS_モバイルただし、/var/mychrootマウントポイントの場合にのみ機能するため、/var/mychrootファイルシステムのサブディレクトリの場合は失敗します/。この場合、他の解決策はありますか?

LD_PRELOAD技術の使用を避け(LD_PRELOAD静的にリンクされた実行可能ファイルは影響を受けません)、技術を使用したいと思います。トラック(2)(もしそうなら、私はstracechrootで実行できません、トラック(2)プロセスがクラッシュしたり停止したり、真の仮想化(パフォーマンスのオーバーヘッドや柔軟性の低いメモリ構成など)を正しく実行するのは難しいです。

要約すると、以下が必要です。

  • の代替chroot(2)システムコール、
  • ルートはこれを使用して、ルート(EUID 0)で実行されるプロセスを制限します。
  • ファイルシステムのサブディレクトリとして/
  • これは防ぎますchdir("..") エスケープ技術
  • 使用しLD_PRELOADない
  • トラック(2)または
  • 仮想化(例:Xen、KVM、QEMU)
  • 最新のLinuxシステムで動作し、
  • パッチされたカーネルがある場合とない場合。

存在しますか?

答え1

上記の特定のエスケープ技術を回避するには、ロックしてchdir("..")再実行する機能を放棄するだけです。エスケープ技術を再度呼び出す必要があるため、これをブロックするだけでは機能しません。chroot(2)/var/mychrootchroot()

Linux機能を使用してこれを行うことができます。CAP_SYS_CHROOT必要な機能を削除するだけですchroot(2)

たとえば、

outside# chroot /var/mychroot
inside# capsh --drop=cap_sys_chroot --
inside# ./escape_chroot
chroot(baz): Operation not permitted

(chroot内の2番目のプロンプトは生成されたシェルから来ますcapsh。たとえば、を使用して別のコマンドを実行させることができますcapsh --drop=cap_sys_chroot -- -c 'exec ./escape_chroot'。)


しかし、より良い技術は、予防できないpivot_root他の多くの攻撃を防ぐことができるためにのみ使用することです。chroot(2)

マウントポイントの場合にのみ機能すると言いましたが、/var/mychroot単にバインドマウントしてマウントポイントにすることができます。

pivot_root刑務所を作成するにはマウントネームスペースを作成する必要があることに注意してください。それ以外の場合は、ファイルシステム内のすべてのプロセスのルートディレクトリを変更しようとします。これはあなたが望むものとは異なる可能性が高いです。

したがって、全体の順序は次のようになります。

outside# unshare -m
outside# mount --bind /var/mychroot /var/mychroot
outside# cd /var/mychroot
outside# mkdir old_root
outside# pivot_root . old_root
limbo# exec chroot .
inside# umount /old_root

(やはり、これらのコマンドの多くは新しいシェルを生成します。それはそれ自体で行われます。unshareコマンドを追加のchroot引数として渡すことでこれらの問題を解決できます。場合によってはスクリプト全体を渡すこともsh -c '...'できます。)

この時点で、あなたは別のマウントネームスペースの刑務所の中にいます。これが単に元のルート(別のデバイスやループデバイスのマウントではない)であるというpivot_root事実は実際には動作を妨げません。/var/mychrootマウントを中央にバインドします。

エスケープコードを実行すると、刑務所が期待どおりに機能することがわかります(エスケープコードに別の方法で指定されていますが)。

inside# touch /inside_jail
inside# ./escape_chroot
Exploit seems to work. =)
inside# ls -ld /inside_jail /old_root
-rw-r--r--.  1 0 0    0 Jan  5 23:45 /inside_jail
dr-xr-xr-x. 20 0 0 4096 Jul  5 23:45 /old_root

ご覧のように、まだ刑務所の中にあります...エクスプロイトコードは少し素朴で、(chrootchdir)仕事が成功すれば刑務所を脱出するのに十分であると仮定していますが、そうではありません。 。

chrootしたがって、この技術を使用して内部タスクをブロックするためにLinux機能を使用する必要がなく、より優れた刑務所を作成することを検討してください(たとえば、刑務所でchroot実際にやりたいことよりも重要な追加機能を作成するなど)。

答え2

/var/mychrootがマウントポイントの場合にのみ機能するため、/var/mychrootが/ファイルシステムのサブディレクトリの場合は失敗します。

任意のディレクトリをマウントポイントに設定できますmount --rbind /var/mychoot /var/mychoot

このステップと必要なその他のステップについてはここで説明します。

Linux名前空間を使用してchrootを実行するには?

実際、私はいろいろなchroot脱出を防ぎたいと思います。

上記の内容をユーザーの名前空間と組み合わせます。

または、seccompmount()たとえば、Dockerを含むプロセス呼び出しを防ぐ方法は次のとおりです。 (ブロックデバイスを2番目にマウントすると、ファイルシステムの2番目のビューが表示され、これはややエスケープと見なされます。)Dockerが許可するシステムコールのリストをコピーします。ルートを脱出する方法はさまざまです。

https://docs.docker.com/engine/security/seccomp/

https://github.com/moby/moby/blob/master/profiles/seccomp/default.json

関連情報