Вопрос

Как можно определить нахождение в chroot-тюрьме без привилегий root?Предположим, что это стандартная система BSD или Linux.Лучшее, что я придумал, — это посмотреть на значение индексного дескриптора «/» и оценить, является ли оно достаточно низким, но мне нужен более точный метод обнаружения.

[edit 20080916 142430 EST] Простого осмотра файловой системы недостаточно, поскольку несложно продублировать такие вещи, как /boot и /dev, чтобы обмануть заключенного пользователя.

[edit 20080916 142950 EST] Для систем Linux проверка неожиданных значений в /proc является разумной, но как насчет систем, которые вообще не поддерживают /proc?

Это было полезно?

Решение

Индексный дескриптор / всегда будет равен 2, если это корневой каталог файловой системы, но вы можете использовать chroot внутри всей файловой системы.Если это просто chroot (а не какая-то другая виртуализация), вы можете запустить mount и сравнить смонтированные файловые системы с тем, что вы видите.Убедитесь, что каждая точка монтирования имеет индексный дескриптор 2.

Другие советы

Если вы не находитесь в chroot, индекс / всегда будет равен 2.Вы можете проверить это, используя

stat -c %i /

или

ls -id /

Интересно, но давайте попробуем найти путь к каталогу chroot.Просить stat на каком устройстве/находится:

stat -c %04D /

Первый байт является старшим для устройства, а второй байт — младшим.Например, 0802 означает старший 8, второстепенный 1.Если вы проверите /dev, вы увидите, что это устройство — /dev/sda2.Если вы являетесь пользователем root, вы можете напрямую создать соответствующее устройство в своем chroot:

mknode /tmp/root_dev b 8 1

Теперь давайте найдем индексный дескриптор, связанный с нашим chroot.debugfs позволяет отображать содержимое файлов, используя номера индексных дескрипторов.Например, 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 имеет индекс 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 имеет индексный дескриптор 915821, а индексный дескриптор 2 является корнем файловой системы.Итак, мой каталог chroot /opt/debian-jail.Конечно, /dev/sda1 может быть смонтирован в другой файловой системе.Вам нужно это проверить (используйте lsof или напрямую выбирая информацию /proc).

В Linux с правами root проверьте, является ли корневой каталог процесса инициализации вашим корневым каталогом.Хотя /proc/1/root всегда является символической ссылкой на /, следуя за ним, вы попадаете в «главный» корневой каталог (при условии, что процесс инициализации не изолирован от 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/exe потому что за пределами chroot все может быть по-другому, если init был обновлен с момента последней загрузки или если chroot находится в основной корневой файловой системе и init жестко связан в нем.

Если у вас нет root-прав, вы можете посмотреть /proc/1/mountinfo и /proc/$$/mountinfo (кратко описано в filesystems/proc.txt в документации ядра Linux).Этот файл доступен для чтения всем и содержит много информации о каждой точке монтирования с точки зрения процесса на файловую систему.Пути в этом файле ограничены chroot, влияющим на процесс чтения, если таковой имеется.Если процесс чтения /proc/1/mountinfo находится в файловой системе, отличной от глобального корня (при условии, что корень pid 1 является глобальным корнем), тогда нет записи для / появляется в /proc/1/mountinfo.Если процесс чтения /proc/1/mountinfo помещается в каталог глобальной корневой файловой системы, затем появляется запись для / появляется в /proc/1/mountinfo, но с другим идентификатором монтирования.Кстати, корневое поле ($4) указывает, где находится chroot в его основной файловой системе.Опять же, это специфично для Linux.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

Весь смысл в том, чтобы предотвратить подобные вещи.Если ваш код должен запускаться в chroot, установите для него флаг при запуске.Если вы взламываете, взломайте:проверьте несколько общих вещей в известных местах, посчитайте файлы в /etc, что-нибудь в /dev.

В системах BSD (проверьте с помощью uname -a) proc всегда должен присутствовать.Проверьте, соответствует ли пара dev/inode /proc/1/exe (используйте stat по этому пути, она будет следовать не по символической ссылке по тексту, а по базовому хуку) /sbin/init.

Проверка корня для индексного дескриптора № 2 также полезна.

В большинстве других систем пользователь root может узнать об этом гораздо быстрее, попробовав трюк взлома fchdir.Если он куда-то пойдет, вы окажетесь в тюрьме chroot.

Я думаю, это зависит от того, почему вы можете оказаться в chroot и были ли предприняты какие-либо усилия для его маскировки.

Я бы проверил /proc, эти файлы автоматически генерируются системными информационными файлами.Ядро заполнит их в корневой файловой системе, но возможно, что они не существуют в файловой системе chroot.

Если /proc корневой файловой системы привязан к /proc в chroot, то вполне вероятно, что между этой информацией и средой chroot существуют некоторые несоответствия.Например, проверьте /proc/mounts.

Аналогично проверьте /sys.

Если вы вошли в chroot с помощью schroot, вы можете проверить значение $debian_chroot.

Мне нужна была та же информация для тюрьмы, работающей на FreeBSD (поскольку Ansible, похоже, не обнаруживает этот сценарий).

В дистрибутиве FreeNAS FreeBSD 11: /proc не установлен на хосте, но находится в тюрьме.Верно ли это и для обычной FreeBSD, я точно не знаю, но процфс:Ушел, но не забыт кажется, предполагает, что это так.В любом случае, вы, вероятно, не захотите пытаться установить его только для определения статуса тюрьмы, и поэтому я не уверен, что его можно использовать в качестве надежного предсказателя пребывания в тюрьме.

Я также исключил использование stat on / как и во FreeNAS, все джейлы имеют собственную файловую систему (т. набор данных ZFS) и, следовательно, / узел на хосте и в тюрьме имеют индекс 4.Я ожидаю, что это обычное явление для FreeBSD 11 в целом.

Итак, подход, который я выбрал, заключался в использовании прокстат на пид 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

Здесь я делаю предположение, что pid 0 всегда будет ядром на хосте, а внутри клетки не будет pid 0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top