20

在没有 root 权限的情况下如何检测到处于 chroot 监狱中?假设一个标准的 BSD 或 Linux 系统。我想出的最好办法是查看“/”的 inode 值并考虑它是否合理地低,但我想要一种更准确的检测方法。

[edit 20080916 142430 EST]仅仅查看文件系统是不够的,因为复制 /boot 和 /dev 之类的东西来欺骗被监禁的用户并不难。

[edit 20080916 142950 EST]对于 Linux 系统,检查 /proc 中的意外值是合理的,但对于不支持 /proc 的系统呢?

4

8 回答 8

14

如果 / 是文件系统的根目录,则 / 的 inode 将始终为 2,但您可能会在完整的文件系统中被 chroot。如果它只是 chroot(而不是其他一些虚拟化),您可以运行 mount 并将已安装的文件系统与您所看到的进行比较。验证每个挂载点都有 inode 2。

于 2008-09-17T23:36:39.733 回答
7

如果您不在 chroot 中,则 / 的 inode 将始终为 2。您可以使用

stat -c %i /

或者

ls -id /

有趣,但让我们尝试找到 chroot 目录的路径。询问stat/位于哪个设备上:

stat -c %04D /

第一个字节是设备的主要字节,最小字节是次要字节。例如,0802,表示major 8,minor 1。如果你签入/dev,你会看到这个设备是/dev/sda2。如果你是 root,你可以直接在你的 chroot 中创建对应的设备:

mknode /tmp/root_dev b 8 1

现在,让我们找到与我们的 chroot 关联的 inode。debugfs 允许使用 inode 编号列出文件的内容。例如,ls -id /返回 923960:

sudo debugfs /tmp/root_dev -R 'ls <923960>'
 923960  (12) .       915821  (32) ..     5636100  (12) var   
5636319  (12) lib    5636322  (12) usr    5636345  (12) tmp   
5636346  (12) sys    5636347  (12) sbin   5636348  (12) run   
5636349  (12) root   5636350  (12) proc   5636351  (12) mnt   
5636352  (12) home   5636353  (12) dev    5636354  (12) boot   
5636355  (12) bin    5636356  (12) etc    5638152  (16) selinux   
5769366  (12) srv    5769367  (12) opt    5769375  (3832) media 

有趣的信息是..入口的inode:915821。我可以问它的内容:

sudo debugfs /tmp/root_dev -R 'ls <915821>'
915821  (12) .              2  (12) ..    923960  (20) debian-jail   
923961  (4052) other-jail  

调用的目录debian-jail有 inode 923960。所以我的 chroot 目录的最后一个组件是debian-jail. 现在让我们看看父目录(inode 2):

sudo debugfs /tmp/root_dev -R 'ls <2>'
      2  (12) .           2  (12) ..          11  (20) lost+found    1046529  (12) home   
 130817  (12) etc    784897  (16) media     3603  (20) initrd.img   
 261633  (12) var    654081  (12) usr     392449  (12) sys            392450  (12) lib   
 784898  (12) root   915715  (12) sbin   1046530  (12) tmp   
1046531  (12) bin    784899  (12) dev     392451  (12) mnt   
 915716  (12) run        12  (12) proc   1046532  (12) boot               13  (16) lib64   
 784945  (12) srv    915821  (12) opt       3604  (3796) vmlinuz 

被调用的目录opt有 inode 915821,inode 2 是文件系统的根目录。所以我的 chroot 目录是/opt/debian-jail. 当然,/dev/sda1 可以安装在另一个文件系统上。您需要检查(使用 lsof 或直接选择信息/proc)。

于 2014-06-16T14:23:24.387 回答
6

在具有 root 权限的 Linux 上,测试 init 进程的根目录是否是您的根目录。虽然/proc/1/root始终是指向 的符号链接/,但跟随它会导致“主”根目录(假设 init 进程未经过 chroot,但这几乎从未完成)。如果/proc没有挂载,你可以打赌你在 chroot 中。

[ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]
# With ash/bash/ksh/zsh
! [ -x /proc/1/root/. ] || [ /proc/1/root/. -ef / ]

这比查看更精确,/proc/1/exeinit因为如果自上次引导以来已升级,或者 chroot 位于主根文件系统上并且init在其中硬链接,则在 chroot之外可能会有所不同。

如果您没有 root 权限,您可以查看/proc/1/mountinfo/proc/$$/mountinfo(简要记录在filesystems/proc.txtLinux 内核文档中)。该文件是世界可读的,并且包含有关文件系统进程视图中每个挂载点的大量信息。该文件中的路径受到影响读取器进程的 chroot 的限制(如果有)。如果进程读取/proc/1/mountinfo被 chroot 到一个不同于全局根的文件系统中(假设 pid 1 的根是全局根),/那么/proc/1/mountinfo. 如果进程读取/proc/1/mountinfo被 chroot 到全局根文件系统上的一个目录,那么一个条目/出现在 中/proc/1/mountinfo,但具有不同的挂载 ID。顺便说一句,根字段($4) 指示 chroot 在其主文件系统中的位置。同样,这是特定于 Linux 的。

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
于 2011-11-09T19:13:57.267 回答
4

防止这样的事情是重点。如果您的代码应该在 chroot 中运行,请让它在启动时设置一个标志。如果你在黑客,黑客:检查已知位置的几个常见的东西,计算 /etc 中的文件,/dev 中的一些东西。

于 2008-09-16T18:14:46.193 回答
4

在 BSD 系统上(使用 uname -a 检查),proc 应该始终存在。检查 /proc/1/exe 的 dev/inode 对(在该路径上使用 stat,它不会通过文本跟随符号链接,而是通过底层钩子)匹配 /sbin/init。

检查 inode #2 的根目录也是一个好方法。

在大多数其他系统上,root 用户可以通过尝试 fchdir root-break 技巧更快地找到。如果它去任何地方,你就在 chroot 监狱里。

于 2008-10-18T18:25:29.027 回答
2

我想这取决于你为什么会在 chroot 中,以及是否有任何努力来掩饰它。

我会检查/proc,这些文件是自动生成的系统信息文件。内核会将这些填充到根文件系统中,但它们可能不存在于 chroot 文件系统中。

如果根文件系统的 /proc 已经绑定到 chroot 中的 /proc,那么很可能该信息与 chroot 环境之间存在一些差异。例如,检查 /proc/mounts。

同样,检查 /sys。

于 2008-09-16T18:22:21.417 回答
2

我想为在 FreeBSD 上运行的监狱提供相同的信息(因为 Ansible 似乎没有检测到这种情况)。

在 FreeBSD 11 的 FreeNAS 发行版上,/proc它不是安装在主机上,而是在监狱内。我不确定在常规 FreeBSD 上是否也是如此,但procfs: Gone But Not Forgotten似乎暗示它是。无论哪种方式,您可能都不想尝试安装它只是为了检测监狱状态,因此我不确定它是否可以用作监狱中的可靠预测器。

我还排除了/在 FreeNAS 上使用 stat on 的可能性,因为所有监狱都有自己的文件系统(即ZFS 数据集),因此/主机上的节点和监狱中的节点都有 inode 4。我希望这在 FreeBSD 11 中很常见一般的。

所以我选择的方法是在 pid 0上使用procstat 。

[root@host ~]# procstat 0
  PID  PPID  PGID   SID  TSID THR LOGIN    WCHAN     EMUL          COMM        
    0     0     0     0     0 1234 -        swapin    -             kernel      
[root@host ~]# echo $?
0
[root@host ~]# jexec guest tcsh
root@guest:/ # procstat 0
procstat: sysctl(kern.proc): No such process
procstat: procstat_getprocs()
root@guest:/ # echo $?
1

我在这里假设 pid 0 将始终是主机上的内核,并且监狱内不会有 pid 0。

于 2018-02-17T18:49:01.540 回答
0

如果您使用 schroot 输入 chroot,那么您可以检查 $debian_chroot 的值。

于 2013-07-25T07:22:59.750 回答