Как можно обнаружить нахождение в chroot jail без прав суперпользователя? Предположим, стандартная система BSD или Linux. Лучшее, что я придумал, - это посмотреть на значение inode для «/» и подумать, является ли оно достаточно низким, но мне нужен более точный метод обнаружения.
[edit 20080916 142430 EST] Недостаточно просто осмотреть файловую систему, так как нетрудно продублировать такие вещи, как / boot и / dev, чтобы обмануть заключенного пользователя.
[edit 20080916 142950 EST] Для систем Linux проверка неожиданных значений в / proc является разумной, но как насчет систем, которые вообще не поддерживают / proc?
Не полностью переносимый (и работает только как suid), но в системах на базе Debian по умолчанию установлен ischroot. См .: manpages.debian.org/jessie/debianutils/ischroot.1.en.html





Предотвращение подобных вещей - вот в чем весь смысл. Если это ваш код, который должен запускаться в chroot, установите флаг при запуске. Если вы взламываете, взломайте: проверьте несколько общих вещей в известных местах, посчитайте файлы в / etc, что-нибудь в / dev.
Я полагаю, это зависит от того, почему вы можете быть в chroot, и были ли какие-либо усилия направлены на его замаскирование.
Я бы проверил / proc, эти файлы автоматически генерируются файлами системной информации. Ядро заполнит их в корневой файловой системе, но возможно, что они не существуют в файловой системе chroot.
Если / proc корневой файловой системы привязан к / proc в chroot, то, вероятно, есть некоторые расхождения между этой информацией и средой chroot. Например, проверьте / proc / mounts.
Аналогичным образом проверьте / sys.
Хотя связать / proc легко, несоответствия в этих данных было бы сложно замаскировать. Ответ принят.
На самом деле, поцарапайте это - как насчет систем, отличных от Linux, у которых нет / proc и друзей для начала?
В вопросе говорится о стандартной системе Linux или BSD. Насколько мне известно, оба имеют / proc.
Inode для / всегда будет 2, если это корневой каталог файловой системы, но вы можете быть помещены в полную файловую систему. Если это просто chroot (а не какая-то другая виртуализация), вы можете запустить mount и сравнить смонтированные файловые системы с тем, что вы видите. Убедитесь, что у каждой точки монтирования есть индекс 2.
Из любопытства, что получает индекс 1?
плохие блоки (исторические / устаревшие)
В linux / sys и / proc оба являются индексными дескрипторами == 1. devtmpfs являются индексными дескрипторами == 3. Классный трюк, но надежен только в «реальных» файловых системах.
Это верно не для каждой файловой системы. В XFS, например, корень имеет индекс 128.
IOW, root_inode=$(stat -c %i /); if [ $root_inode -ne 2 -a $root_inode -ne 128 ]; ...
@Topaz индекс 1 представляет точку монтирования, которая используется в данный момент (что-то смонтировано). Я заметил, что это не относится к devtmpfs.
@SpamapS Неправда о devtmpfs в файловой системе Arch Linux ext4. ls -di /dev показывает 1025.
В системах BSD (проверьте с помощью uname -a) всегда должна присутствовать proc. Проверьте, соответствует ли пара dev / inode / proc / 1 / exe (используйте stat на этом пути, он будет следовать за символической ссылкой не по тексту, а по базовому хуку) / sbin / init.
Проверка корня для inode # 2 также является хорошей задачей.
В большинстве других систем пользователь root может узнать это намного быстрее, попробовав трюк с взломом root-прав fchdir. Если он куда-то попадет, вы окажетесь в тюрьме chroot.
+1 .. устройство + индексный дескриптор / proc / 1 / root или / proc / 1 / exe - вот как несколько программ в Debian и Ubuntu определяют, запускаются ли они в chroot.
Если /sbin/init жестко привязан к среде chroot, он будет иметь тот же dev / inode, что и запущенный: ложно-отрицательный. Если /sbin/init был обновлен после загрузки системы, он будет иметь другой dev / inode даже в реальном корне: ложное срабатывание.
Ложноотрицательный результат здесь требует, чтобы корневой индексный дескриптор не был 2. Ложноположительный результат очень редок.
В Linux с правами root проверьте, является ли корневой каталог процесса инициализации вашим корневым каталогом. Хотя /proc/1/root всегда является символической ссылкой на /, переход по ней ведет к «главному» корневому каталогу (при условии, что процесс инициализации не привязан к корневому каталогу, но это практически никогда не выполняется). Если /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, но с другим идентификатором монтирования. Между прочим, корневое поле () указывает, где находится chroot в своей главной файловой системе. Опять же, это характерно для Linux.
[ "$(awk '= = "/" {print }' </proc/1/mountinfo)" != "$(awk '= = "/" {print }' </proc/$$/mountinfo)" ]
Если вы вошли в chroot с помощью schroot, вы можете проверить значение $ debian_chroot.
Если вы не находитесь в 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
Теперь давайте найдем inode, связанный с нашим chroot. 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
Интересная информация - это индекс записи ..: 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. Теперь посмотрим на родительский каталог (индекс 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).
Мне нужна была та же информация для тюрьмы, работающей на FreeBSD (поскольку Ansible, похоже, не обнаруживает этот сценарий).
В дистрибутиве FreeNAS FreeBSD 11 /proc не смонтирован на хосте, но находится внутри тюрьмы. Верно ли это и для обычной FreeBSD, я точно не знаю, но procfs: ушел, но не забыт, похоже, предполагает, что это так. В любом случае вы, вероятно, не захотите пытаться установить его только для определения статуса тюрьмы, и поэтому я не уверен, что его можно использовать в качестве надежного предиктора нахождения в тюрьме.
Я также исключил использование stat на /, поскольку, конечно же, на FreeNAS все тюрьмы имеют свою собственную файловую систему (например, набор данных ZFS), и поэтому узел / на хосте и в тюрьме имеет индекс 4. Я ожидаю, что это распространено во FreeBSD 11 в Общее.
Итак, подход, на котором я остановился, заключался в использовании procstat на 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
Я делаю предположение, что pid 0 всегда будет ядром на хосте, а внутри тюрьмы не будет pid 0.
См. Также Как мне узнать, что я использую chroot?