więzienia chroot są specyficzne dla bsd. chroot w systemie Linux nie jest więzieniem. Ostatnio sprawdziłem, że nie można chrootować jako użytkownik.
ksenoterrakid
1
@ Xenoterracide Więzienia są specyficzne dla BSD, ale chroot jest powszechnie znany jako „więzienie chroot” w społeczności Linuksa. Jest dość zdezorientowany.
pehrs
2
Co próbujesz zrobić i dlaczego? Istnieją narzędzia takie jak fakechroot i schroot, które sprawiają, że stanowią praktyczną alternatywę w zależności od twoich wymagań.
W systemie Linux wywołanie systemowe chroot (2) może być wykonane tylko przez uprzywilejowany proces. Możliwości potrzebne procesowi to CAP_SYS_CHROOT.
Powód, dla którego nie możesz chrootować jako użytkownik, jest dość prosty. Załóżmy, że masz program setuid, taki jak sudo, który sprawdza / etc / sudoers, czy możesz coś zrobić. Teraz włóż go do chroot chroot z własnymi / etc / sudoers. Nagle masz natychmiastową eskalację uprawnień.
Możliwe jest zaprojektowanie programu, aby sam się chrootował i uruchamiał jako proces setuid, ale ogólnie uważa się to za zły projekt. Dodatkowe bezpieczeństwo chroota nie motywuje problemów bezpieczeństwa z setuidem.
Dzięki nowym możliwościom przestrzeni nazw w systemie Linux może być możliwe utworzenie (nieudostępnianie) nowej przestrzeni nazw „użytkownika”, w której byłby „osadzony” użytkownik root, i wykonanie chroottego.
imz - Ivan Zakharyaschev
1
@ imz - IvanZakharyaschev Masz całkowitą rację i mam nadzieję, że nie przeszkadza ci, że mogłem napisać to jako łatwą do sprawdzenia odpowiedź.
hvd
@hvd Świetnie! Musi być bardzo przydatny, ponieważ pokazuje, jak używać nowych nieznanych funkcji Linuksa za pomocą konkretnych poleceń.
imz - Ivan Zakharyaschev
6
@ imz - IvanZakharyaschev komentuje odpowiedź pehrsa, że może to być możliwe dzięki wprowadzeniu przestrzeni nazw, ale nie zostało to przetestowane i opublikowane jako odpowiedź. Tak, to naprawdę umożliwia użytkownikom innym niż root korzystanie z chroot.
Biorąc pod uwagę statycznie połączony dashi statycznie połączony busyboxoraz działającą bashpowłokę działającą jako użytkownik inny niż root:
Identyfikator użytkownika root w tej przestrzeni nazw jest mapowany do innego niż root ID użytkownika zewnątrz tej przestrzeni nazw, i vice versa, dlatego pliki systemowe przedstawia posiadane przez bieżącego użytkownika jako własność ID użytkownika 0. regularny ls -al root, bez unshare, czy pokaż je jako własność bieżącego użytkownika.
Uwaga: dobrze wiadomo, że procesy, które są zdolne do użycia chroot, są zdolne do wyrwania się z chroot. Ponieważ unshare -rprzyznałby chrootuprawnienia zwykłemu użytkownikowi, byłoby to zagrożeniem bezpieczeństwa, gdyby było to dozwolone w chrootśrodowisku. Rzeczywiście jest to niedozwolone i kończy się niepowodzeniem w przypadku:
CLONE_NEWUSER został określony w flagach, a program wywołujący znajduje się w środowisku chroot (tzn. Katalog główny dzwoniącego nie pasuje do katalogu głównego przestrzeni nazw montowania, w której się znajduje).
Uruchomienie pivot_root w przestrzeni nazw montowania ma podobny efekt jak chroot, ale pozwala uniknąć konfliktu z przestrzeniami nazw użytkowników.
Timothy Baldwin
1
Można uciec z chroot lub zamontować przestrzeń nazw, schodząc do / proc, jeśli jest to proces poza tym samym UID w tym samym lub potomnym PID i przestrzeniach użytkownika.
Timothy Baldwin
2
Teraz chcesz patrzeć na LXC (Linux Containers) zamiast na chroot / BSD. Jest gdzieś pomiędzy chrootem a maszyną wirtualną, co daje dużą kontrolę bezpieczeństwa i ogólną konfigurowalność. Uważam, że wszystko, czego potrzebujesz, aby uruchomić go jako użytkownik, to być członkiem grupy, która jest właścicielem niezbędnych plików / urządzeń, ale mogą również dotyczyć możliwości / uprawnień systemowych. Tak czy inaczej, powinno to być bardzo wykonalne, ponieważ LXC jest dość nowy, długo po dodaniu SELinux itp. Do jądra Linux.
Pamiętaj również, że możesz po prostu pisać skrypty jako root, ale dać użytkownikom bezpieczne uprawnienia do uruchamiania tych skryptów (bez hasła, jeśli chcesz, ale upewnij się, że skrypt jest bezpieczny) przy użyciu sudo.
Połączenie fakeroot / fakechroot daje symulację chroot do prostych potrzeb, takich jak tworzenie archiwów tar, w których pliki wydają się być własnością root. Strona man Fakechroot to http://linux.die.net/man/1/fakechroot .
Nie otrzymujesz jednak żadnych nowych uprawnień, ale jeśli posiadasz katalog (np. Fałszywe dystrybucje) przed wywołaniem
To fajny pomysł, ale wydaje się nieprzewidywalnie obsługiwać dowiązania symboliczne. Mój ~/fake-distroużywa busyboksa, do którego prowadzi dowiązanie symboliczne ls, mvi innych popularnych narzędzi /bin/busybox. Jeśli wyraźnie dzwonię /bin/busybox mv ..., wszystko działa, ale jeśli dzwonię /bin/mv ..., dostaję sh: /bin/mv: not found. Ustawienie export FAKECHROOT_EXCLUDE_PATH=/przed uruchomieniem fakechroot naprawia ten objaw, ale potem psuje się na innych dowiązaniach symbolicznych (np /usr/bin/vim -> /usr/bin/vim.vim.).
Ponkadoodle,
może FAKECHROOT_EXCLUDE_PATH = /: / usr pomógłby wtedy?
sylvainulg,
1
Wydaje się, że dzięki przestrzeniom nazw użytkowników można w rzeczywistości chrootować bez rootowania. Oto przykładowy program, który pokazuje, że jest to możliwe. Dopiero zacząłem badać, jak działają przestrzenie nazw systemu Linux, więc nie jestem całkowicie pewien, czy ten kod jest najlepszą praktyką, czy nie.
Zapisz jako user_chroot.cc. Kompiluj z g++ -o user_chroot user_chroot.cc. Zastosowanie jest ./user_chroot /path/to/new_rootfs.
// references:
// [1]: http://man7.org/linux/man-pages/man7/user_namespaces.7.html
// [2]: http://man7.org/linux/man-pages/man2/unshare.2.html
#include <sched.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include <cstdio>
#include <cstring>
int main(int argc, char** argv) {
if(argc < 2) {
printf("Usage: %s <rootfs>\n", argv[0]);
}
int uid = getuid();
int gid = getgid();
printf("Before unshare, uid=%d, gid=%d\n", uid, gid);
// First, unshare the user namespace and assume admin capability in the
// new namespace
int err = unshare(CLONE_NEWUSER);
if(err) {
printf("Failed to unshare user namespace\n");
return 1;
}
// write a uid/gid map
char file_path_buf[100];
int pid = getpid();
printf("My pid: %d\n", pid);
sprintf(file_path_buf, "/proc/%d/uid_map", pid);
int fd = open(file_path_buf, O_WRONLY);
if(fd == -1) {
printf("Failed to open %s for write [%d] %s\n", file_path_buf, errno,
strerror(errno));
} else {
printf("Writing : %s (fd=%d)\n", file_path_buf, fd);
err = dprintf(fd, "%d %d 1\n", uid, uid);
if(err == -1) {
printf("Failed to write contents [%d]: %s\n", errno,
strerror(errno));
}
close(fd);
}
sprintf(file_path_buf, "/proc/%d/setgroups", pid);
fd = open(file_path_buf, O_WRONLY);
if(fd == -1) {
printf("Failed to open %s for write [%d] %s\n", file_path_buf, errno,
strerror(errno));
} else {
dprintf(fd, "deny\n");
close(fd);
}
sprintf(file_path_buf, "/proc/%d/gid_map", pid);
fd = open(file_path_buf, O_WRONLY);
if(fd == -1) {
printf("Failed to open %s for write [%d] %s\n", file_path_buf, errno,
strerror(errno));
} else {
printf("Writing : %s (fd=%d)\n", file_path_buf, fd);
err = dprintf(fd, "%d %d 1\n", gid, gid);
if(err == -1) {
printf("Failed to write contents [%d]: %s\n", errno,
strerror(errno));
}
close(fd);
}
// Now chroot into the desired directory
err = chroot(argv[1]);
if(err) {
printf("Failed to chroot\n");
return 1;
}
// Now drop admin in our namespace
err = setresuid(uid, uid, uid);
if(err) {
printf("Failed to set uid\n");
}
err = setresgid(gid, gid, gid);
if(err) {
printf("Failed to set gid\n");
}
// and start a shell
char argv0[] = "bash";
char* new_argv[] = {
argv0,
NULL
};
err = execvp("/bin/bash", new_argv);
if(err) {
perror("Failed to start shell");
return -1;
}
}
Przetestowałem to na minimalnych rootfsach generowanych przy pomocy multistrap (wykonywanych jako non-root). Niektóre pliki systemowe, takie jak /etc/passwdi /etc/groupszostały skopiowane z rootfów hosta do rootfów guest.
Nie. Jeśli dobrze pamiętam, to chroot robi coś na poziomie jądra, co temu zapobiega. Nie pamiętam, co to było. Zbadałem to, gdy zadzierałem z narzędziem Catalyst Build Gentoo (a chroot w Gentoo jest taki sam jak chroot w Ubuntu). Choć byłoby to możliwe bez hasła ... takie rzeczy są pozostawione sferze potencjalnych luk w zabezpieczeniach i upewnienia się, że wiesz, co robisz.
Odpowiedzi:
W systemie Linux wywołanie systemowe chroot (2) może być wykonane tylko przez uprzywilejowany proces. Możliwości potrzebne procesowi to CAP_SYS_CHROOT.
Powód, dla którego nie możesz chrootować jako użytkownik, jest dość prosty. Załóżmy, że masz program setuid, taki jak sudo, który sprawdza / etc / sudoers, czy możesz coś zrobić. Teraz włóż go do chroot chroot z własnymi / etc / sudoers. Nagle masz natychmiastową eskalację uprawnień.
Możliwe jest zaprojektowanie programu, aby sam się chrootował i uruchamiał jako proces setuid, ale ogólnie uważa się to za zły projekt. Dodatkowe bezpieczeństwo chroota nie motywuje problemów bezpieczeństwa z setuidem.
źródło
chroot
tego.@ imz - IvanZakharyaschev komentuje odpowiedź pehrsa, że może to być możliwe dzięki wprowadzeniu przestrzeni nazw, ale nie zostało to przetestowane i opublikowane jako odpowiedź. Tak, to naprawdę umożliwia użytkownikom innym niż root korzystanie z chroot.
Biorąc pod uwagę statycznie połączony
dash
i statycznie połączonybusybox
oraz działającąbash
powłokę działającą jako użytkownik inny niż root:Identyfikator użytkownika root w tej przestrzeni nazw jest mapowany do innego niż root ID użytkownika zewnątrz tej przestrzeni nazw, i vice versa, dlatego pliki systemowe przedstawia posiadane przez bieżącego użytkownika jako własność ID użytkownika 0. regularny
ls -al root
, bezunshare
, czy pokaż je jako własność bieżącego użytkownika.Uwaga: dobrze wiadomo, że procesy, które są zdolne do użycia
chroot
, są zdolne do wyrwania się zchroot
. Ponieważunshare -r
przyznałbychroot
uprawnienia zwykłemu użytkownikowi, byłoby to zagrożeniem bezpieczeństwa, gdyby było to dozwolone wchroot
środowisku. Rzeczywiście jest to niedozwolone i kończy się niepowodzeniem w przypadku:który pasuje do dokumentacji unshare (2) :
źródło
Teraz chcesz patrzeć na LXC (Linux Containers) zamiast na chroot / BSD. Jest gdzieś pomiędzy chrootem a maszyną wirtualną, co daje dużą kontrolę bezpieczeństwa i ogólną konfigurowalność. Uważam, że wszystko, czego potrzebujesz, aby uruchomić go jako użytkownik, to być członkiem grupy, która jest właścicielem niezbędnych plików / urządzeń, ale mogą również dotyczyć możliwości / uprawnień systemowych. Tak czy inaczej, powinno to być bardzo wykonalne, ponieważ LXC jest dość nowy, długo po dodaniu SELinux itp. Do jądra Linux.
Pamiętaj również, że możesz po prostu pisać skrypty jako root, ale dać użytkownikom bezpieczne uprawnienia do uruchamiania tych skryptów (bez hasła, jeśli chcesz, ale upewnij się, że skrypt jest bezpieczny) przy użyciu sudo.
źródło
Połączenie fakeroot / fakechroot daje symulację chroot do prostych potrzeb, takich jak tworzenie archiwów tar, w których pliki wydają się być własnością root. Strona man Fakechroot to http://linux.die.net/man/1/fakechroot .
Nie otrzymujesz jednak żadnych nowych uprawnień, ale jeśli posiadasz katalog (np. Fałszywe dystrybucje) przed wywołaniem
teraz szuka jakiegoś polecenia, jakbyś był rootem i posiadał wszystko w fałszywej dystrybucji.
źródło
~/fake-distro
używa busyboksa, do którego prowadzi dowiązanie symbolicznels
,mv
i innych popularnych narzędzi/bin/busybox
. Jeśli wyraźnie dzwonię/bin/busybox mv ...
, wszystko działa, ale jeśli dzwonię/bin/mv ...
, dostajęsh: /bin/mv: not found
. Ustawienieexport FAKECHROOT_EXCLUDE_PATH=/
przed uruchomieniem fakechroot naprawia ten objaw, ale potem psuje się na innych dowiązaniach symbolicznych (np/usr/bin/vim -> /usr/bin/vim.vim
.).Wydaje się, że dzięki przestrzeniom nazw użytkowników można w rzeczywistości chrootować bez rootowania. Oto przykładowy program, który pokazuje, że jest to możliwe. Dopiero zacząłem badać, jak działają przestrzenie nazw systemu Linux, więc nie jestem całkowicie pewien, czy ten kod jest najlepszą praktyką, czy nie.
Zapisz jako
user_chroot.cc
. Kompiluj zg++ -o user_chroot user_chroot.cc
. Zastosowanie jest./user_chroot /path/to/new_rootfs
.Przetestowałem to na minimalnych rootfsach generowanych przy pomocy multistrap (wykonywanych jako non-root). Niektóre pliki systemowe, takie jak
/etc/passwd
i/etc/groups
zostały skopiowane z rootfów hosta do rootfów guest.źródło
Failed to unshare user namespace
działa dla mnie na Linuksie 4.12.10 (Arch Linux).unshare
połączenia. Możesz także wypróbować tę wersję Pythona, która może mieć lepsze komunikaty o błędach: github.com/cheshirekow/uchrootNie. Jeśli dobrze pamiętam, to chroot robi coś na poziomie jądra, co temu zapobiega. Nie pamiętam, co to było. Zbadałem to, gdy zadzierałem z narzędziem Catalyst Build Gentoo (a chroot w Gentoo jest taki sam jak chroot w Ubuntu). Choć byłoby to możliwe bez hasła ... takie rzeczy są pozostawione sferze potencjalnych luk w zabezpieczeniach i upewnienia się, że wiesz, co robisz.
źródło