ユーザー名前空間

Reading time: 13 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

基本情報

ユーザー名前空間は、ユーザーおよびグループIDマッピングの隔離を提供するLinuxカーネルの機能であり、各ユーザー名前空間が独自のユーザーおよびグループIDのセットを持つことを可能にします。この隔離により、異なるユーザー名前空間で実行されているプロセスは、同じユーザーおよびグループIDを数値的に共有していても、異なる特権と所有権を持つことができます

ユーザー名前空間は、各コンテナが独自の独立したユーザーおよびグループIDのセットを持つべきコンテナ化に特に便利であり、コンテナとホストシステム間のセキュリティと隔離を向上させます。

仕組み:

  1. 新しいユーザー名前空間が作成されると、空のユーザーおよびグループIDマッピングのセットから始まります。これは、新しいユーザー名前空間で実行されるプロセスが名前空間の外で特権を持たないことを意味します
  2. IDマッピングは、新しい名前空間のユーザーおよびグループIDと親(またはホスト)名前空間のIDとの間で確立できます。これにより、新しい名前空間のプロセスが親名前空間のユーザーおよびグループIDに対応する特権と所有権を持つことができます。ただし、IDマッピングは特定の範囲やIDのサブセットに制限でき、プロセスに付与される特権を細かく制御できます。
  3. ユーザー名前空間内では、プロセスは名前空間内の操作に対して完全なルート特権(UID 0)を持つことができますが、名前空間の外では制限された特権を持ちます。これにより、コンテナはホストシステム上で完全なルート特権を持たずに、自身の名前空間内でルートのような機能を持って実行できます
  4. プロセスは、setns()システムコールを使用して名前空間間を移動したり、unshare()またはclone()システムコールをCLONE_NEWUSERフラグと共に使用して新しい名前空間を作成したりできます。プロセスが新しい名前空間に移動するか、新しい名前空間を作成すると、その名前空間に関連付けられたユーザーおよびグループIDマッピングを使用し始めます。

ラボ:

異なる名前空間を作成する

CLI

bash
sudo unshare -U [--mount-proc] /bin/bash

新しいインスタンスの /proc ファイルシステムを --mount-proc パラメータを使用してマウントすることで、新しいマウントネームスペースがそのネームスペースに特有のプロセス情報の正確で隔離されたビューを持つことを保証します。

エラー: bash: fork: メモリを割り当てることができません

unshare-f オプションなしで実行されると、Linux が新しい PID (プロセス ID) ネームスペースを処理する方法のためにエラーが発生します。重要な詳細と解決策は以下の通りです:

  1. 問題の説明
  • Linux カーネルはプロセスが unshare システムコールを使用して新しいネームスペースを作成することを許可します。しかし、新しい PID ネームスペースの作成を開始するプロセス(「unshare」プロセスと呼ばれる)は新しいネームスペースに入らず、その子プロセスのみが入ります。
  • %unshare -p /bin/bash% を実行すると、unshare と同じプロセスで /bin/bash が開始されます。その結果、/bin/bash とその子プロセスは元の PID ネームスペースに存在します。
  • 新しいネームスペース内の /bin/bash の最初の子プロセスは PID 1 になります。このプロセスが終了すると、他にプロセスがない場合、PID 1 は孤児プロセスを引き取る特別な役割を持っているため、ネームスペースのクリーンアップがトリガーされます。Linux カーネルはそのネームスペース内での PID 割り当てを無効にします。
  1. 結果
  • 新しいネームスペース内での PID 1 の終了は PIDNS_HASH_ADDING フラグのクリーンアップを引き起こします。これにより、新しいプロセスを作成する際に alloc_pid 関数が新しい PID を割り当てることに失敗し、「メモリを割り当てることができません」というエラーが発生します。
  1. 解決策
  • この問題は、unshare-f オプションを使用することで解決できます。このオプションは、unshare が新しい PID ネームスペースを作成した後に新しいプロセスをフォークします。
  • %unshare -fp /bin/bash% を実行すると、unshare コマンド自体が新しいネームスペース内で PID 1 になります。これにより、/bin/bash とその子プロセスはこの新しいネームスペース内に安全に収容され、PID 1 の早期終了を防ぎ、通常の PID 割り当てを可能にします。

unshare-f フラグで実行されることを保証することで、新しい PID ネームスペースが正しく維持され、/bin/bash とそのサブプロセスがメモリ割り当てエラーに遭遇することなく動作できるようになります。

Docker

bash
docker run -ti --name ubuntu1 -v /usr:/ubuntu1 ubuntu bash

ユーザー名前空間を使用するには、Dockerデーモンを --userns-remap=default で起動する必要があります(Ubuntu 14.04では、/etc/default/docker を変更し、その後 sudo service docker restart を実行することで行えます)

プロセスがどの名前空間にいるかを確認する

bash
ls -l /proc/self/ns/user
lrwxrwxrwx 1 root root 0 Apr  4 20:57 /proc/self/ns/user -> 'user:[4026531837]'

Dockerコンテナからユーザーマップを確認することができます:

bash
cat /proc/self/uid_map
0          0 4294967295  --> Root is root in host
0     231072      65536  --> Root is 231072 userid in host

ホストから次のように:

bash
cat /proc/<pid>/uid_map

すべてのユーザー名前空間を見つける

bash
sudo find /proc -maxdepth 3 -type l -name user -exec readlink {} \; 2>/dev/null | sort -u
# Find the processes with an specific namespace
sudo find /proc -maxdepth 3 -type l -name user -exec ls -l  {} \; 2>/dev/null | grep <ns-number>

ユーザー名前空間に入る

bash
nsenter -U TARGET_PID --pid /bin/bash

また、ルートでなければ他のプロセスの名前空間に入ることはできません。そして、ディスクリプタがそれを指していない限り(例えば /proc/self/ns/user)、他の名前空間に入ることはできません

新しいユーザー名前空間を作成する(マッピング付き)

bash
unshare -U [--map-user=<uid>|<name>] [--map-group=<gid>|<name>] [--map-root-user] [--map-current-user]
bash
# Container
sudo unshare -U /bin/bash
nobody@ip-172-31-28-169:/home/ubuntu$ #Check how the user is nobody

# From the host
ps -ef | grep bash # The user inside the host is still root, not nobody
root       27756   27755  0 21:11 pts/10   00:00:00 /bin/bash

Recovering Capabilities

ユーザー名前空間の場合、新しいユーザー名前空間が作成されると、その名前空間に入るプロセスには完全な権限のセットが付与されます。これらの権限により、プロセスはファイルシステムのマウント、デバイスの作成、ファイルの所有権の変更などの特権操作を実行できますが、そのユーザー名前空間のコンテキスト内でのみ実行できます。

例えば、ユーザー名前空間内でCAP_SYS_ADMIN権限を持っている場合、ファイルシステムのマウントなど、この権限を通常必要とする操作を実行できますが、あなたのユーザー名前空間のコンテキスト内でのみです。この権限を使用して実行する操作は、ホストシステムや他の名前空間には影響しません。

warning

したがって、新しいユーザー名前空間内に新しいプロセスを取得することがすべての権限を戻すことになります(CapEff: 000001ffffffffff)としても、実際には名前空間に関連するもののみを使用できます(例えばマウント)が、すべての権限を使用できるわけではありません。したがって、これだけではDockerコンテナから脱出するには不十分です。

bash
# There are the syscalls that are filtered after changing User namespace with:
unshare -UmCpf  bash

Probando: 0x067 . . . Error
Probando: 0x070 . . . Error
Probando: 0x074 . . . Error
Probando: 0x09b . . . Error
Probando: 0x0a3 . . . Error
Probando: 0x0a4 . . . Error
Probando: 0x0a7 . . . Error
Probando: 0x0a8 . . . Error
Probando: 0x0aa . . . Error
Probando: 0x0ab . . . Error
Probando: 0x0af . . . Error
Probando: 0x0b0 . . . Error
Probando: 0x0f6 . . . Error
Probando: 0x12c . . . Error
Probando: 0x130 . . . Error
Probando: 0x139 . . . Error
Probando: 0x140 . . . Error
Probando: 0x141 . . . Error

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする