hacktricks/linux-hardening/privilege-escalation/docker-security/namespaces/mount-namespace.md

7.4 KiB
Raw Blame History

挂载命名空间

从零开始学习AWS黑客技术成为专家 htARTEHackTricks AWS Red Team Expert

支持HackTricks的其他方式

基本信息

挂载命名空间是Linux内核的一个功能提供了一组进程看到的文件系统挂载点的隔离。每个挂载命名空间都有自己的文件系统挂载点集一个命名空间中对挂载点的更改不会影响其他命名空间。这意味着在不同挂载命名空间中运行的进程可以对文件系统层次结构有不同的视图。

挂载命名空间在容器化中特别有用,每个容器应该有自己的文件系统和配置,与其他容器和主机系统隔离开来。

工作原理:

  1. 创建新的挂载命名空间时,它会使用父命名空间的挂载点的副本进行初始化。这意味着在创建时,新命名空间与其父命名空间共享相同的文件系统视图。但是,命名空间内的挂载点的任何后续更改都不会影响父命名空间或其他命名空间。
  2. 当进程修改其命名空间内的挂载点,例如挂载或卸载文件系统时,更改仅限于该命名空间,不会影响其他命名空间。这允许每个命名空间拥有自己独立的文件系统层次结构。
  3. 进程可以使用setns()系统调用在命名空间之间移动,或者使用带有CLONE_NEWNS标志的unshare()clone()系统调用创建新的命名空间。当进程移动到新的命名空间或创建一个新的命名空间时,它将开始使用与该命名空间关联的挂载点。
  4. 文件描述符和inode在命名空间之间共享,这意味着如果一个命名空间中的进程有指向文件的打开文件描述符,它可以将该文件描述符传递给另一个命名空间中的进程两个进程将访问同一个文件。但是,由于挂载点的差异,两个命名空间中文件的路径可能不相同。

实验:

创建不同的命名空间

命令行界面

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

通过使用参数--mount-proc挂载/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命名空间后fork一个新进程。
  • 执行%unshare -fp /bin/bash%确保unshare命令本身成为新命名空间中的PID 1。然后/bin/bash及其子进程安全地包含在此新命名空间中防止PID 1过早退出并允许正常的PID分配。

通过确保unshare使用-f标志运行新的PID命名空间将得到正确维护使/bin/bash及其子进程能够正常运行,而不会遇到内存分配错误。

Docker

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

检查您的进程位于哪个命名空间

ls -l /proc/self/ns/mnt
lrwxrwxrwx 1 root root 0 Apr  4 20:30 /proc/self/ns/mnt -> 'mnt:[4026531841]'

查找所有挂载命名空间

{% code overflow="wrap" %}

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

{% endcode %}

进入挂载命名空间

nsenter -m TARGET_PID --pid /bin/bash

此外,只有root用户才能进入另一个进程命名空间。而且,没有指向它的描述符(如/proc/self/ns/mnt),你无法进入其他命名空间。

由于新挂载点只能在命名空间内访问,因此可能存在包含只能从中访问的敏感信息的命名空间。

挂载某物

# Generate new mount ns
unshare -m /bin/bash
mkdir /tmp/mount_ns_example
mount -t tmpfs tmpfs /tmp/mount_ns_example
mount | grep tmpfs # "tmpfs on /tmp/mount_ns_example"
echo test > /tmp/mount_ns_example/test
ls /tmp/mount_ns_example/test # Exists

# From the host
mount | grep tmpfs # Cannot see "tmpfs on /tmp/mount_ns_example"
ls /tmp/mount_ns_example/test # Doesn't exist

参考资料

从零开始学习AWS黑客技术 htARTE (HackTricks AWS Red Team Expert)

支持HackTricks的其他方式