Apakah mungkin bagi pengguna non-root untuk menjalankan proses chroot di Ubuntu?
Apakah mungkin bagi pengguna non-root untuk menjalankan proses chroot di Ubuntu?
Jawaban:
Di Linux chroot (2) system call hanya dapat dilakukan oleh proses yang diistimewakan. Kemampuan yang dibutuhkan proses adalah CAP_SYS_CHROOT.
Alasan Anda tidak dapat melakukan chroot sebagai pengguna sangat sederhana. Asumsikan Anda memiliki program setuid seperti sudo yang memeriksa / etc / sudoers jika Anda diizinkan untuk melakukan sesuatu. Sekarang letakkan di chroot chroot dengan / etc / sudoers Anda sendiri. Tiba-tiba Anda mengalami peningkatan hak istimewa instan.
Dimungkinkan untuk merancang program untuk chroot sendiri dan menjalankannya sebagai proses setuid, tetapi ini umumnya dianggap desain yang buruk. Keamanan ekstra chroot tidak memotivasi masalah keamanan dengan setuid.
chroot
itu.
@ imz - IvanZakharyaschev mengomentari jawaban pehrs bahwa dimungkinkan dengan pengenalan ruang nama, tetapi ini belum diuji dan diposting sebagai jawaban. Ya, itu memang memungkinkan pengguna non-root menggunakan chroot.
Diberi tautan-statis dash
, dan tautan-terhubung-statis busybox
, serta bash
shell yang berjalan sebagai non-root:
$ 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
ID pengguna root di namespace itu dipetakan ke ID pengguna non-root di luar namespace itu, dan sebaliknya, itulah sebabnya sistem menunjukkan file yang dimiliki oleh pengguna saat ini yang dimiliki oleh ID pengguna 0. Sebuah reguler ls -al root
, tanpa unshare
, tidak perlihatkan mereka sebagai milik pengguna saat ini.
Catatan: diketahui bahwa proses yang dapat digunakan chroot
, mampu keluar dari a chroot
. Karena unshare -r
akan memberikan chroot
izin kepada pengguna biasa, itu akan menjadi risiko keamanan jika diizinkan di dalam chroot
lingkungan. Memang, itu tidak diizinkan, dan gagal dengan:
unshare: unshare gagal: Operasi tidak diizinkan
yang cocok dengan dokumentasi unshare (2) :
EPERM (sejak Linux 3.9)
CLONE_NEWUSER ditentukan dalam flag dan penelepon berada di lingkungan chroot (yaitu direktori root pemanggil tidak cocok dengan direktori root dari mount namespace di mana ia berada).
Saat ini, Anda ingin melihat LXC (Linux Containers) alih-alih penjara chroot / BSD. Itu ada di suatu tempat antara chroot dan mesin virtual, memberi Anda banyak kontrol keamanan dan konfigurasi umum. Saya percaya semua yang Anda butuhkan untuk menjalankannya sebagai pengguna adalah menjadi anggota grup yang memiliki file / perangkat yang diperlukan, tetapi mungkin juga ada kemampuan / izin sistem yang terlibat. Either way, itu harus sangat bisa dilakukan, karena LXC cukup baru, lama setelah SELinux dll ditambahkan ke kernel Linux.
Juga, ingatlah bahwa Anda hanya dapat menulis skrip sebagai root tetapi memberikan izin aman kepada pengguna untuk menjalankan skrip tersebut (tanpa kata sandi jika Anda suka, tetapi pastikan skrip aman) menggunakan sudo.
Kombinasi fakeroot / fakechroot memberikan simultan chroot untuk kebutuhan sederhana seperti memproduksi arsip tar di mana file tampaknya dimiliki oleh root. Halaman manual Fakechroot adalah http://linux.die.net/man/1/fakechroot .
Anda tidak mendapatkan izin baru, tetapi jika Anda memiliki direktori (mis. Distro palsu) sebelum memohon
fakechroot fakeroot chroot ~/fake-distro some-command
sekarang cari beberapa perintah seperti Anda root dan memiliki semuanya dalam distro-palsu.
~/fake-distro
menggunakan busybox, yang menghubungkan ls
, mv
dan utilitas umum lainnya /bin/busybox
. Jika saya secara eksplisit menelepon /bin/busybox mv ...
, semuanya berfungsi, tetapi jika saya menelepon /bin/mv ...
saya dapat sh: /bin/mv: not found
. Pengaturan export FAKECHROOT_EXCLUDE_PATH=/
sebelum menjalankan fakechroot memperbaiki gejala itu, tetapi kemudian rusak pada symlink lain (misalnya /usr/bin/vim -> /usr/bin/vim.vim
).
Tampaknya dengan ruang nama pengguna sebenarnya memungkinkan untuk melakukan chroot tanpa root. Berikut adalah contoh program yang menunjukkan bahwa itu mungkin. Saya baru mulai mengeksplorasi bagaimana ruang nama linux bekerja dan jadi saya tidak sepenuhnya yakin apakah kode ini praktik terbaik atau tidak.
Simpan sebagai user_chroot.cc
. Kompilasi dengan g++ -o user_chroot user_chroot.cc
. Penggunaan adalah ./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;
}
}
Saya telah menguji ini pada rootf minimal yang dihasilkan dengan multistrap (dieksekusi sebagai non-root). Beberapa file sistem suka /etc/passwd
dan /etc/groups
disalin dari host rootfs ke rootf tamu.
Failed to unshare user namespace
untuk saya di linux 4.12.10 (Arch Linux).
unshare
panggilan yang gagal . Anda juga dapat mencoba versi python ini yang mungkin memiliki pesan kesalahan yang lebih baik: github.com/cheshirekow/uchroot
Tidak. Jika saya mengingat dengan benar ada beberapa hal tingkat kernel yang chroot lakukan yang mencegahnya. Saya tidak ingat benda apa itu. Saya menyelidiki kembali ketika mengacaukan dengan alat Catalyst Build Gentoo (dan chroot pada gentoo sama dengan chroot di ubuntu). Meskipun mungkin untuk mewujudkannya tanpa sandiwara ... tetapi hal-hal seperti itu diserahkan pada bidang kerentanan keamanan potensial dan memastikan Anda tahu apa yang Anda lakukan.