Rilevamento di una prigione chroot dall'interno
Domanda
Come si può scoprire di essere in una prigione chroot senza privilegi di root?Supponiamo un sistema BSD o Linux standard.La cosa migliore che mi è venuta in mente è stata guardare il valore dell'inode per "/" e considerare se è ragionevolmente basso, ma vorrei un metodo più accurato per il rilevamento.
[edit 20080916 142430 EST]
Guardare semplicemente il filesystem non è sufficiente, poiché non è difficile duplicare cose come /boot e /dev per ingannare l'utente imprigionato.
[edit 20080916 142950 EST]
Per i sistemi Linux, è ragionevole verificare la presenza di valori imprevisti all'interno di /proc, ma che dire dei sistemi che non supportano /proc in primo luogo?
Soluzione
L'inode per / sarà sempre 2 se è la directory root di un filesystem, ma potresti essere sottoposto a chroot all'interno di un filesystem completo.Se si tratta solo di chroot (e non di qualche altra virtualizzazione), potresti eseguire mount e confrontare i filesystem montati con quello che vedi.Verificare che ogni punto di montaggio abbia l'inode 2.
Altri suggerimenti
Se non sei in chroot, l'inode per / sarà sempre 2.Puoi verificarlo utilizzando
stat -c %i /
O
ls -id /
Interessante, ma proviamo a trovare il percorso della directory chroot.Chiedi a stat
su quale dispositivo/si trova:
stat -c %04D /
Il primo byte è il maggiore del dispositivo e l'ultimo byte è il minore.Ad esempio, 0802 significa maggiore 8, minore 1.Se controlli in /dev, vedrai che questo dispositivo è /dev/sda2.Se sei root puoi creare direttamente il dispositivo corrispondente nel tuo chroot:
mknode /tmp/root_dev b 8 1
Ora troviamo l'inode associato al nostro chroot.debugfs consente di elencare il contenuto dei file utilizzando i numeri di inode.Per esempio, ls -id /
restituito 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
Informazioni interessanti sono inode di ..
iscrizione:915821.Posso chiederne il contenuto:
sudo debugfs /tmp/root_dev -R 'ls <915821>'
915821 (12) . 2 (12) .. 923960 (20) debian-jail
923961 (4052) other-jail
Elenco chiamato debian-jail
ha l'inode 923960.Quindi l'ultimo componente della mia directory chroot è debian-jail
.Vediamo ora la directory principale (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
Elenco chiamato opt
ha l'inode 915821 e l'inode 2 è la root del filesystem.Quindi la mia directory chroot è /opt/debian-jail
.Sicuro, /dev/sda1
può essere montato su un altro filesystem.È necessario verificarlo (usare lsof o raccogliere direttamente le informazioni /proc
).
Su Linux con permessi root, verifica se la directory root del processo init è la tua directory root.Sebbene /proc/1/root
è sempre un collegamento simbolico a /
, seguirlo porta alla directory root "master" (assumendo che il processo init non sia in chroot, ma questo non viene quasi mai fatto).Se /proc
non è montato, puoi scommettere che sei in 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 / ]
Questo è più preciso di guardando /proc/1/exe
perché potrebbe essere diverso al di fuori di un chroot se init
è stato aggiornato dall'ultimo avvio o se il chroot si trova sul filesystem root principale e init
è strettamente collegato in esso.
Se non hai i permessi di root, puoi guardare /proc/1/mountinfo
E /proc/$$/mountinfo
(brevemente documentato in filesystems/proc.txt
nella documentazione del kernel Linux).Questo file è leggibile da tutti e contiene molte informazioni su ciascun punto di montaggio nella vista del filesystem del processo.I percorsi in quel file sono limitati dal chroot che influenza il processo di lettura, se presente.Se il processo di lettura /proc/1/mountinfo
viene eseguito il chroot in un filesystem diverso dalla radice globale (assumendo che la radice di pid 1 sia la radice globale), quindi nessuna voce per /
appare in /proc/1/mountinfo
.Se il processo di lettura /proc/1/mountinfo
viene chroot in una directory sul filesystem root globale, quindi una voce per /
appare in /proc/1/mountinfo
, ma con un ID di montaggio diverso.Per inciso, il campo radice ($4
) indica dove si trova il chroot nel suo filesystem principale.Ancora una volta, questo è specifico per Linux.
[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
Prevenire cose del genere è il punto centrale.Se è il tuo codice che dovrebbe essere eseguito nel chroot, imposta un flag all'avvio.Se stai hackerando, hackera:controlla diverse cose comuni in posizioni conosciute, conta i file in /etc, qualcosa in /dev.
Sui sistemi BSD (controllare con uname -a), proc dovrebbe essere sempre presente.Controlla se la coppia dev/inode di /proc/1/exe (usa stat su quel percorso, non seguirà il collegamento simbolico tramite testo ma tramite l'hook sottostante) corrisponde a /sbin/init.
Anche controllare la root per l'inode n. 2 è utile.
Sulla maggior parte degli altri sistemi, un utente root può scoprirlo molto più velocemente tentando il trucco di rottura root di fchdir.Se va da qualche parte sei in una prigione chroot.
Immagino che dipenda dal motivo per cui potresti trovarti in un chroot e se è stato fatto qualche sforzo per mascherarlo.
Controllerei /proc, questi file sono file di informazioni di sistema generati automaticamente.Il kernel li popolerà nel filesystem root, ma è possibile che non esistano nel filesystem chroot.
Se /proc del filesystem root è stato associato a /proc nel chroot, è probabile che ci siano alcune discrepanze tra tali informazioni e l'ambiente chroot.Controlla /proc/mounts per esempio.
Allo stesso modo, controlla /sys.
Se sei entrato nel chroot con schroot, puoi controllare il valore di $debian_chroot.
Volevo le stesse informazioni per una jail in esecuzione su FreeBSD (poiché Ansible non sembra rilevare questo scenario).
Sulla distribuzione FreeNAS di FreeBSD 11, /proc
non è montato sull'host, ma è all'interno della jail.Se questo sia vero anche su FreeBSD normale, non lo so per certo, ma procf:Andato ma non dimenticato sembra suggerire che lo sia.In ogni caso, probabilmente non vorrai provare a montarlo solo per rilevare lo stato di prigione e quindi non sono sicuro che possa essere usato come predittore affidabile dell'essere all'interno di una prigione.
Ho anche escluso l'utilizzo di stat on /
poiché certamente su FreeNAS a tutte le jail viene assegnato il proprio file system (ad es. un set di dati ZFS) e quindi il /
il nodo sull'host e nella prigione hanno entrambi l'inode 4.Mi aspetto che questo sia comune su FreeBSD 11 in generale.
Quindi l'approccio che ho scelto è stato l'utilizzo procstat su 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
Sto partendo dal presupposto che pid 0 sarà sempre il kernel sull'host e non ci sarà un pid 0 all'interno della prigione.