PID Namespace

Reading time: 10 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をサポートする

基本情報

PID (プロセス識別子) ネームスペースは、Linux カーネルの機能であり、プロセスの隔離を提供します。これにより、一群のプロセスが他のネームスペースの PID とは別の一意の PID のセットを持つことができます。これは、プロセスの隔離がセキュリティとリソース管理に不可欠なコンテナ化に特に役立ちます。

新しい PID ネームスペースが作成されると、そのネームスペース内の最初のプロセスには PID 1 が割り当てられます。このプロセスは新しいネームスペースの「init」プロセスとなり、そのネームスペース内の他のプロセスを管理する責任を負います。ネームスペース内で作成される各後続プロセスは、そのネームスペース内で一意の PID を持ち、これらの PID は他のネームスペースの PID とは独立しています。

PID ネームスペース内のプロセスの視点から見ると、同じネームスペース内の他のプロセスのみを見ることができます。他のネームスペースのプロセスを認識せず、従来のプロセス管理ツール(例: kill, wait など)を使用して相互作用することはできません。これにより、プロセスが互いに干渉するのを防ぐための隔離レベルが提供されます。

仕組み:

  1. 新しいプロセスが作成されると(例: clone() システムコールを使用)、プロセスは新しいまたは既存の PID ネームスペースに割り当てられます。新しいネームスペースが作成されると、プロセスはそのネームスペースの「init」プロセスになります
  2. カーネルは、新しいネームスペース内の PID と親ネームスペース内の対応する PID とのマッピングを維持します(つまり、新しいネームスペースが作成されたネームスペース)。このマッピングは、カーネルが必要に応じて PID を変換できるようにします。たとえば、異なるネームスペースのプロセス間で信号を送信する際などです。
  3. PID ネームスペース内のプロセスは、同じネームスペース内の他のプロセスのみを見たり相互作用したりできます。彼らは他のネームスペースのプロセスを認識せず、彼らの PID はそのネームスペース内で一意です。
  4. PID ネームスペースが破棄されると(例: ネームスペースの「init」プロセスが終了すると)、そのネームスペース内のすべてのプロセスが終了します。これにより、ネームスペースに関連するすべてのリソースが適切にクリーンアップされます。

ラボ:

異なるネームスペースを作成する

CLI

bash
sudo unshare -pf --mount-proc /bin/bash
エラー: 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とそのサブプロセスがメモリ割り当てエラーに遭遇することなく動作できるようになります。

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

Docker

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

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

bash
ls -l /proc/self/ns/pid
lrwxrwxrwx 1 root root 0 Apr  3 18:45 /proc/self/ns/pid -> 'pid:[4026532412]'

すべてのPID名前空間を見つける

bash
sudo find /proc -maxdepth 3 -type l -name pid -exec readlink {} \; 2>/dev/null | sort -u

初期(デフォルト)のPID名前空間からのrootユーザーは、すべてのプロセスを見ることができます。新しいPID名前空間内のプロセスも含まれています。これが、すべてのPID名前空間を見ることができる理由です。

PID名前空間に入る

bash
nsenter -t TARGET_PID --pid /bin/bash

PID ネームスペースにデフォルトのネームスペースから入ると、すべてのプロセスを見ることができます。そして、その PID ns のプロセスは新しい bash を PID ns で見ることができます。

また、root でない限り、他のプロセスの PID ネームスペースに入ることはできません。そして、ディスクリプタがそれを指していない限り、他のネームスペースに入ることはできません(例えば /proc/self/ns/pid のように)。

References

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をサポートする