Kök olmayan bir kullanıcının Ubuntu'da bir chroot işlemi çalıştırması mümkün mü?
Kök olmayan bir kullanıcının Ubuntu'da bir chroot işlemi çalıştırması mümkün mü?
Yanıtlar:
Linux'ta chroot (2) sistem çağrısı yalnızca ayrıcalıklı bir işlemle yapılabilir. Sürecin ihtiyacı olan yetenek CAP_SYS_CHROOT'tur.
Kullanıcı olarak oturum açamamanızın nedeni oldukça basittir. Sudo gibi bir setuid programınız olduğunu varsayalım. Şimdi kendi / etc / sudoer'larınızla birlikte bir kroke koyun. Aniden bir ayrıcalık yükselmesi yaşarsınız.
Kendini geliştirmek ve setuid işlemi olarak çalıştırmak için bir program tasarlamak mümkündür, ancak bu genellikle kötü tasarım olarak kabul edilir. Kökün ekstra güvenliği setuid ile ilgili güvenlik sorunlarını motive etmez.
chroot
.
@ imz - IvanZakharyaschev pehrs'in cevabını isim alanlarının girişiyle mümkün olabileceğini söyledi, ancak bu test edilmedi ve bir cevap olarak yayınlanmadı. Evet, bu aslında root olmayan bir kullanıcının chroot kullanmasını mümkün kılar.
Statik olarak bağlanmış dash
ve statik olarak bağlanmış busybox
ve bash
kök olmayan olarak çalışan bir çalışan kabuk verildiğinde :
$ mkdir root
$ cp /path/to/dash root
$ cp /path/to/busybox root
$ unshare -r bash -c 'chroot root /dash -c "/busybox ls -al /"'
total 2700
drwxr-xr-x 2 0 0 4096 Dec 2 19:16 .
drwxr-xr-x 2 0 0 4096 Dec 2 19:16 ..
drwxr-xr-x 1 0 0 1905240 Dec 2 19:15 busybox
drwxr-xr-x 1 0 0 847704 Dec 2 19:15 dash
Bu ad alanında kök kullanıcı kimliği bu ad alanının kök olmayan kullanıcı kimliği dışarıya eşleştirilir ve kullanıcı kimliğine göre 0. Düzenli olunan güncel bir kullanıcıya ait sistem gösterileri dosyaları neden tam tersi, ls -al root
olmadan, unshare
yapar geçerli kullanıcıya ait olarak göster.
Not: Kullanabilen işlemlerin chroot
a chroot
. Yana unshare -r
vereceğini chroot
sıradan bir kullanıcıya izin bir iç izin verildi, eğer bir güvenlik riski olacaktır chroot
çevre. Gerçekten de, buna izin verilmez ve başarısız olur:
unshare: unshare başarısız oldu: İşleme izin verilmiyor
paylaşılmayan (2) belgelere uyan :
EPERM (Linux 3.9'dan beri)
CLONE_NEWUSER bayraklarda belirtildi ve arayan bir chroot ortamında (yani, arayanın kök dizini, içinde bulunduğu bağlama ad alanının kök diziniyle eşleşmiyor).
Bu günlerde, chroot / BSD hapishanesi yerine LXC'ye (Linux Kapsayıcıları) bakmak istiyorsunuz. Bir chroot ve sanal makine arasında bir yerdedir ve size çok fazla güvenlik kontrolü ve genel yapılandırılabilirlik sağlar. Bir kullanıcı olarak çalıştırmak için gereken tek şeyin, gerekli dosyalara / cihazlara sahip olan grubun bir üyesi olması gerektiğine inanıyorum, ancak yetenekler / sistem izinleri de olabilir. Her iki durumda da, Linux çekirdeğine SELinux vb. Eklendikten çok sonra LXC oldukça yeni olduğu için çok yapılabilir.
Ayrıca, komut dosyalarını kök olarak yazabileceğinizi, ancak sudo kullanarak kullanıcılara bu komut dosyalarını çalıştırmak için güvenli izin verdiğinizi (isterseniz bir parola olmadan, ancak komut dosyasının güvenli olduğundan emin olun) unutmayın.
Fakeroot / fakechroot kombinasyonu, dosyaların köklere ait olduğu görünen katran arşivleri üretmek gibi basit ihtiyaçlar için bir benzetme simülatörü verir. Fakechroot manpage http://linux.die.net/man/1/fakechroot .
Yine de yeni bir izin almazsınız, ancak çağırmadan önce bir dizininiz varsa (örneğin, sahte dağıtım)
fakechroot fakeroot chroot ~/fake-distro some-command
şimdi kök gibi bir komut arar ve sahte dağıtımdaki her şeye sahip olursun.
~/fake-distro
kullanımları busybox, sembolik bağlar ls
, mv
ve diğer ortak programları /bin/busybox
. Eğer açıkça ararsam /bin/busybox mv ...
, işler işe yarar, ama ararsam /bin/mv ...
alırım sh: /bin/mv: not found
. export FAKECHROOT_EXCLUDE_PATH=/
Fakechroot'u çalıştırmadan önce ayar yapmak bu semptomu düzeltir, ancak daha sonra diğer sembollere (örn /usr/bin/vim -> /usr/bin/vim.vim
.
Görünüşe göre kullanıcı-ad alanları ile root olmadan krootlamak mümkün. İşte bunun mümkün olduğunu gösteren bir örnek program. Yalnızca linux ad alanlarının nasıl çalıştığını keşfetmeye başladım ve bu kodun en iyi yöntem olup olmadığından tamamen emin değilim.
Farklı kaydet user_chroot.cc
. İle derleyin g++ -o user_chroot user_chroot.cc
. Kullanımı ./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;
}
}
Ben çok köklü (kök olmayan olarak yürütülen) ile oluşturulan minimal rootfs üzerinde bu test ettim. Bazı sistem dosyaları gibi /etc/passwd
ve /etc/groups
konuk rootfs içine konak rootfs kopyalanmıştır.
Failed to unshare user namespace
Linux 4.12.10'da (Arch Linux) başarısız oluyor.
unshare
. Daha iyi hata mesajlarına sahip olabilecek bu python sürümünü de deneyebilirsiniz: github.com/cheshirekow/uchroot
Hayır. Doğru hatırlıyorsam, krootun bunu engelleyen bazı çekirdek düzeyinde bir şey var. O şeyin ne olduğunu hatırlamıyorum. Gentoo'nun Catalyst Build aracıyla uğraşırken onu tekrar araştırdım (ve gentoo üzerinde bir kroket ubuntu üzerinde bir chroot ile aynı). Her ne kadar bir parola olmadan gerçekleşmek mümkün olsa da ... ancak bu tür şeyler potansiyel güvenlik açıkları alanına bırakılır ve ne yaptığınızı bildiğinizden emin olunur.