Detectando una cárcel chroot desde dentro
Pregunta
¿Cómo se puede detectar estar en una cárcel chroot sin privilegios de root?Supongamos un sistema BSD o Linux estándar.Lo mejor que se me ocurrió fue observar el valor del inodo para "/" y considerar si es razonablemente bajo, pero me gustaría un método de detección más preciso.
[edit 20080916 142430 EST]
Simplemente mirar alrededor del sistema de archivos no es suficiente, ya que no es difícil duplicar cosas como /boot y /dev para engañar al usuario encarcelado.
[edit 20080916 142950 EST]
Para los sistemas Linux, comprobar si hay valores inesperados dentro de /proc es razonable, pero ¿qué pasa con los sistemas que no soportan /proc en primer lugar?
Solución
El inodo para / siempre será 2 si es el directorio raíz de un sistema de archivos, pero es posible que tenga un chroot dentro de un sistema de archivos completo.Si es solo chroot (y no alguna otra virtualización), puede ejecutar mount y comparar los sistemas de archivos montados con lo que ve.Verifique que cada punto de montaje tenga el inodo 2.
Otros consejos
Si no estás en un chroot, el inodo para / siempre será 2.Puedes comprobarlo usando
stat -c %i /
o
ls -id /
Interesante, pero intentemos encontrar la ruta del directorio chroot.Preguntar a stat
en qué dispositivo / se encuentra:
stat -c %04D /
El primer byte es el mayor del dispositivo y el byte menor es el menor.Por ejemplo, 0802 significa 8 mayor, 1 menor.Si registra /dev, verá que este dispositivo es /dev/sda2.Si eres root, puedes crear directamente el dispositivo correspondiente en tu chroot:
mknode /tmp/root_dev b 8 1
Ahora, busquemos el inodo asociado a nuestro chroot.debugfs permite enumerar el contenido de los archivos utilizando números de inodo.Por ejemplo, ls -id /
devuelto 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
Información interesante es el inodo de ..
entrada:915821.Puedo preguntar su contenido:
sudo debugfs /tmp/root_dev -R 'ls <915821>'
915821 (12) . 2 (12) .. 923960 (20) debian-jail
923961 (4052) other-jail
directorio llamado debian-jail
tiene inodo 923960.Entonces el último componente de mi directorio chroot es debian-jail
.Veamos ahora el directorio principal (inodo 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
directorio llamado opt
tiene el inodo 915821 y el inodo 2 es la raíz del sistema de archivos.Entonces mi directorio chroot es /opt/debian-jail
.Seguro, /dev/sda1
puede estar montado en otro sistema de archivos.Debe verificar eso (use lsof o seleccione información directamente /proc
).
En Linux con permisos de root, pruebe si el directorio raíz del proceso de inicio es su directorio raíz.A pesar de /proc/1/root
es siempre un vínculo simbólico con /
, a continuación se accede al directorio raíz "maestro" (suponiendo que el proceso de inicio no esté chroot, pero eso casi nunca se hace).Si /proc
no está montado, puedes apostar que estás en un 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 / ]
Esto es más preciso que mirando a /proc/1/exe
porque eso podría ser diferente fuera de un chroot si init
se ha actualizado desde el último arranque o si el chroot está en el sistema de archivos raíz principal y init
está fuertemente ligado a ello.
Si no tiene permisos de root, puede mirar /proc/1/mountinfo
y /proc/$$/mountinfo
(brevemente documentado en filesystems/proc.txt
en la documentación del kernel de Linux).Este archivo es legible en todo el mundo y contiene mucha información sobre cada punto de montaje en la vista del proceso del sistema de archivos.Las rutas en ese archivo están restringidas por el chroot que afecta al proceso de lectura, si lo hay.Si el proceso de lectura /proc/1/mountinfo
está chroot en un sistema de archivos que es diferente de la raíz global (asumiendo que la raíz del pid 1 es la raíz global), entonces no hay entrada para /
aparece en /proc/1/mountinfo
.Si el proceso de lectura /proc/1/mountinfo
se chroot a un directorio en el sistema de archivos raíz global, luego una entrada para /
aparece en /proc/1/mountinfo
, pero con una identificación de montaje diferente.Por cierto, el campo raíz ($4
) indica dónde está el chroot en su sistema de archivos maestro.Nuevamente, esto es específico de Linux.
[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
Prevenir cosas así es el objetivo.Si es su código el que se supone que debe ejecutarse en el chroot, haga que establezca un indicador al inicio.Si estás pirateando, piratea:verifique varias cosas comunes en ubicaciones conocidas, cuente los archivos en/etc, algo en/dev.
En sistemas BSD (verifique con uname -a), proc siempre debe estar presente.Compruebe si el par dev/inode de /proc/1/exe (use stat en esa ruta, no seguirá el enlace simbólico por texto sino por el enlace subyacente) coincide con /sbin/init.
Comprobar la raíz del inodo n.° 2 también es una buena opción.
En la mayoría de los demás sistemas, un usuario root puede descubrirlo mucho más rápido intentando el truco fchdir para romper el root.Si va a alguna parte, estás en una cárcel chroot.
Supongo que depende de por qué podrías estar en un chroot y de si se ha hecho algún esfuerzo para disfrazarlo.
Verificaría /proc, estos archivos son archivos de información del sistema generados automáticamente.El kernel los completará en el sistema de archivos raíz, pero es posible que no existan en el sistema de archivos chroot.
Si el /proc del sistema de archivos raíz se ha vinculado a /proc en el chroot, entonces es probable que existan algunas discrepancias entre esa información y el entorno chroot.Consulte /proc/mounts, por ejemplo.
De manera similar, verifique /sys.
Si ingresó al chroot con schroot, entonces puede verificar el valor de $debian_chroot.
Quería la misma información para una cárcel que se ejecuta en FreeBSD (ya que Ansible no parece detectar este escenario).
Sobre la distribución FreeNAS de FreeBSD 11, /proc
no está montado en el host, pero está dentro de la cárcel.Si esto también es cierto en FreeBSD normal, no lo sé con certeza, pero procesos:Ido pero no olvidado parece sugerir que lo es.De cualquier manera, probablemente no quieras intentar montarlo solo para detectar el estado de la cárcel y, por lo tanto, no estoy seguro de que pueda usarse como un predictor confiable de estar dentro de una cárcel.
También descarté usar stat on /
Como ciertamente en FreeNAS todas las cárceles tienen su propio sistema de archivos (es decir, un conjunto de datos ZFS) y por lo tanto el /
El nodo en el host y en la cárcel tienen el inodo 4.Espero que esto sea común en FreeBSD 11 en general.
Así que el enfoque que elegí fue usar procstat en el pid 0.
[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
Aquí estoy asumiendo que el pid 0 siempre será el kernel en el host y que no habrá un pid 0 dentro de la cárcel.