Question

Comment peut-on détecter l’arrivée dans une prison chroot sans privilèges root? Supposons un système BSD ou Linux standard. Le mieux que j’ai proposé était de regarder la valeur d’inode pour "/". et examiner si elle est raisonnablement basse, mais j'aimerais une méthode de détection plus précise.

[modifier 20080916 142430 EST] Il ne suffit pas de chercher dans le système de fichiers, car il n'est pas difficile de dupliquer des éléments tels que / boot et / dev pour tromper l'utilisateur emprisonné.

[modifier 20080916 142950 EST] Pour les systèmes Linux, il est raisonnable de rechercher des valeurs inattendues dans / proc, mais qu'en est-il des systèmes qui ne prennent pas en charge / proc en premier lieu?

Était-ce utile?

La solution

L'inode pour / sera toujours 2 s'il s'agit du répertoire racine d'un système de fichiers, mais vous pouvez être chrooté à l'intérieur d'un système de fichiers complet. S'il ne s'agit que de chroot (et non d'une autre virtualisation), vous pouvez exécuter mount et comparer les systèmes de fichiers montés avec ce que vous voyez. Vérifiez que chaque point de montage a l’inode 2.

Autres conseils

Si vous n'êtes pas dans un chroot, l'inode pour / sera toujours 2. Vous pouvez vérifier que l'utilisation de

stat -c %i /

ou

ls -id /

Intéressant, mais essayons de trouver le chemin du répertoire chroot. Demander à stat sur quel périphérique / se trouve:

stat -c %04D /

Le premier octet est majeur de périphérique et ne doit pas être mineur. Par exemple, 0802, signifie majeur 8, mineur 1. Si vous enregistrez / dev, vous verrez que ce périphérique est / dev / sda2. Si vous êtes root, vous pouvez créer directement le périphérique correspondant dans votre chroot:

mknode /tmp/root_dev b 8 1

Maintenant, trouvons l'inode associé à notre chroot. debugfs permet de lister le contenu des fichiers en utilisant des numéros d'inode. Par exemple, ls -id / a renvoyé 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 

L'information intéressante est l'inode de l'entrée .. : 915821. Je peux demander son contenu:

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

appelé debian-jail contient l'inode 923960. Le dernier composant de mon répertoire chroot est donc debian-jail . Voyons maintenant le répertoire parent (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 

Le répertoire appelé opt contient l'inode 915821 et l'inode 2 est la racine du système de fichiers. Donc, mon répertoire chroot est / opt / debian-jail . Bien sûr, / dev / sda1 peut être monté sur un autre système de fichiers. Vous devez vérifier cela (utilisez lsof ou choisissez directement les informations / proc ).

Sous Linux avec les autorisations root, vérifiez si le répertoire racine du processus init est votre répertoire racine. Bien que / proc / 1 / root soit toujours un lien symbolique vers / , il est suivi du message & # 8220; maître & # 8221; répertoire racine (en supposant que le processus init ne soit pas chrooté, mais c'est rarement fait). Si / proc n'est pas monté, vous pouvez parier que vous êtes dans 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 / ]

C’est plus précis que regarder / proc / 1 / exe car cela pourrait être différent en dehors d'un chroot si init a été mis à niveau depuis le dernier démarrage ou si le chroot est sur le système de fichiers racine principal et init y est lié durement.

Si vous ne disposez pas des autorisations root, vous pouvez consulter / proc / 1 / mountinfo et / proc / $$ / mountinfo (documenté brièvement dans systèmes de fichiers / proc.txt dans la documentation du noyau Linux ) Ce fichier est lisible par tout le monde et contient de nombreuses informations sur chaque point de montage dans la vue du processus du système de fichiers par le processus. Les chemins dans ce fichier sont limités par le chroot affectant le processus de lecture, le cas échéant. Si le processus qui lit / proc / 1 / mountinfo est chrooté dans un système de fichiers différent de la racine globale (en supposant que la racine de pid 1 est la racine globale), aucune entrée pour / apparaît dans / proc / 1 / mountinfo . Si le processus qui lit / proc / 1 / mountinfo est chrooté dans un répertoire du système de fichiers racine global, une entrée pour / apparaît dans / proc / 1 / mountinfo , mais avec un identifiant de montage différent. Incidemment, le champ racine ( $ 4 ) indique où se trouve le chroot dans son système de fichiers maître. Encore une fois, cela est spécifique à Linux.

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

La prévention de ce genre de choses est l’essentiel. Si votre code est censé être exécuté dans le chroot, demandez-lui de définir un indicateur au démarrage. Si vous piratez, hack: vérifiez plusieurs choses courantes dans des emplacements connus, comptez les fichiers dans / etc, quelque chose dans / dev.

Sur les systèmes BSD (vérifiez avec uname -a), proc doit toujours être présent. Vérifiez si la paire dev / inode de / proc / 1 / exe (utilisez stat sur ce chemin, elle ne suivra pas le lien symbolique par du texte mais par le crochet sous-jacent) correspond à / sbin / init.

Vérifier la racine pour l’inode n ° 2 est également bon.

Sur la plupart des autres systèmes, un utilisateur root peut le découvrir plus rapidement en tentant de résoudre le problème de fchdir. Si ça se passe n'importe où, vous êtes dans une prison chroot.

Je suppose que cela dépend de la raison pour laquelle vous êtes dans un chroot et de la question de savoir si un effort quelconque a été fait pour le déguiser.

Je vérifierais / proc, ces fichiers sont des fichiers d’informations système générés automatiquement. Le noyau les peuplera dans le système de fichiers racine, mais il est possible qu’ils n’existent pas dans le système de fichiers chroot.

Si le processus / proc du système de fichiers racine a été lié à / proc dans le chroot, il est probable qu'il existe des différences entre ces informations et l'environnement chroot. Vérifiez par exemple / proc / mounts.

De même, vérifiez / sys.

Si vous avez entré le chroot avec schroot, vous pouvez alors vérifier la valeur de $ debian_chroot.

Je voulais les mêmes informations pour une prison tournant sous FreeBSD (Ansible ne semble pas détecter ce scénario).

Sur la distribution FreeNAS de FreeBSD 11, / proc n'est pas monté sur l'hôte, mais dans la prison. Je ne sais pas avec certitude si cela est également vrai pour FreeBSD classique, mais procfs: perdu mais pas oublié semble suggérer que tel est le cas. Quoi qu’il en soit, vous ne voudriez probablement pas essayer de le monter uniquement pour détecter le statut de prison. Par conséquent, je ne suis pas sûr que cela puisse être utilisé comme un prédicteur fiable de l’intégration dans une prison.

J'ai également exclu l'utilisation de stat sur / , car toutes les prisons de FreeNAS se voient attribuer leur propre système de fichiers (c'est-à-dire un jeu de données ZFS ) et donc le nœud / sur l'hôte et dans la prison ont tous deux l'inode 4. Je m'attends à ce qu'il en soit ainsi commun sur FreeBSD 11 en général.

L’approche que j’ai choisie a donc été d’utiliser procstat sur le 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

Je suppose ici que pid 0 sera toujours le noyau de l'hôte et qu'il n'y aura pas de pid 0 dans la prison.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top