¿Es posible que un usuario no root ejecute un proceso chroot en Ubuntu?
¿Es posible que un usuario no root ejecute un proceso chroot en Ubuntu?
Respuestas:
En Linux, la llamada al sistema chroot (2) solo se puede realizar mediante un proceso con privilegios. La capacidad que necesita el proceso es CAP_SYS_CHROOT.
La razón por la que no puedes hacer chroot como usuario es bastante simple. Suponga que tiene un programa setuid como sudo que comprueba / etc / sudoers si se le permite hacer algo. Ahora póngalo en un chroot chroot con sus propios / etc / sudoers. De repente tienes una escalada de privilegios instantánea.
Es posible diseñar un programa para que se ejecute a sí mismo y ejecutarlo como un proceso setuid, pero esto generalmente se considera un mal diseño. La seguridad adicional del chroot no motiva los problemas de seguridad con el setuid.
chroot
luego realizarlo .
@ imz - IvanZakharyaschev comenta sobre la respuesta de pehrs de que puede ser posible con la introducción de espacios de nombres, pero esto no ha sido probado y publicado como respuesta. Sí, eso sí hace posible que un usuario no root use chroot.
Dado un enlace estático dash
, y un enlace estático busybox
, y una ejecuciónbash
shell en ejecución que se ejecuta como no 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
La ID de usuario raíz en ese espacio de nombres se asigna a la ID de usuario no root fuera de ese espacio de nombres, y viceversa, razón por la cual el sistema muestra los archivos propiedad del usuario actual como propiedad de la ID de usuario 0. Una regular ls -al root
, sinunshare
, hace mostrarlos como propiedad del usuario actual.
Nota: es bien sabido que los procesos que son capaces de usar chroot
, son capaces de salir de a chroot
. Dado unshare -r
que otorgaría chroot
permisos a un usuario ordinario, sería un riesgo de seguridad si se permitiera dentro de unchroot
entorno. De hecho, no está permitido y falla con:
unshare: unshare falló: operación no permitida
que coincide con el unshare (2) :
EPERM (desde Linux 3.9)
CLONE_NEWUSER se especificó en banderas y la persona que llama está en un entorno chroot (es decir, el directorio raíz de la persona que llama no coincide con el directorio raíz del espacio de nombres de montaje en el que reside).
En estos días, desea mirar LXC (Contenedores de Linux) en lugar de la cárcel chroot / BSD. Está en algún lugar entre un chroot y una máquina virtual, lo que le brinda mucho control de seguridad y una configuración general. Creo que todo lo que necesita para ejecutarlo como usuario es ser miembro del grupo que posee los archivos / dispositivos necesarios, pero también puede haber capacidades / permisos del sistema involucrados. De cualquier manera, debería ser muy factible, ya que LXC es bastante reciente, mucho después de que SELinux, etc., se haya agregado al kernel de Linux.
Además, tenga en cuenta que solo puede escribir scripts como root, pero otorgue a los usuarios un permiso seguro para ejecutar esos scripts (sin una contraseña si lo desea, pero asegúrese de que el script sea seguro) usando sudo.
La combinación de fakeroot / fakechroot proporciona un simulacro de chroot para necesidades simples, como la producción de archivos tar donde los archivos parecen ser propiedad de root. La página de manual de Fakechroot es http://linux.die.net/man/1/fakechroot .
Sin embargo, no obtiene ningún permiso nuevo, pero si posee un directorio (p. Ej., False-distro) antes de invocar
fakechroot fakeroot chroot ~/fake-distro some-command
ahora busca algún comando como si fuera root y sea dueño de todo dentro de fake-distro.
~/fake-distro
usa busybox, que enlaces simbólicos ls
, mv
y otras utilidades comunes para /bin/busybox
. Si llamo explícitamente /bin/busybox mv ...
, las cosas funcionan, pero si llamo /bin/mv ...
obtengo sh: /bin/mv: not found
. La configuración export FAKECHROOT_EXCLUDE_PATH=/
antes de ejecutar el fakechroot corrige ese síntoma, pero luego se rompe en otros enlaces simbólicos (por ejemplo /usr/bin/vim -> /usr/bin/vim.vim
).
Parece que con espacios de nombres de usuario es posible de hecho chroot sin root. Aquí hay un programa de ejemplo que demuestra que es posible. Solo he comenzado a explorar cómo funcionan los espacios de nombres de Linux y, por lo tanto, no estoy completamente seguro de si este código es la mejor práctica o no.
Guardar como user_chroot.cc
. Compilar con g++ -o user_chroot user_chroot.cc
. El uso es ./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;
}
}
He probado esto en un rootfs mínimo generado con multistrap (ejecutado como no root). Algunos archivos del sistema tienen gusto /etc/passwd
y /etc/groups
fueron copiados de los rootfs del host en los rootfs invitados.
Failed to unshare user namespace
Me falla en Linux 4.12.10 (Arch Linux).
unshare
llamada fallida . También puede probar esta versión de Python que podría tener mejores mensajes de error: github.com/cheshirekow/uchroot
No. Si recuerdo correctamente, hay algo de nivel de kernel que hace chroot que lo impide. No recuerdo qué era esa cosa. Lo investigué cuando me metí con la herramienta Catalyst Build de Gentoo (y un chroot en gentoo es lo mismo que un chroot en ubuntu). Aunque sería posible hacer que suceda sin una contraseña ... pero esas cosas se dejan al ámbito de las posibles vulnerabilidades de seguridad y se aseguran de que sepa lo que está haciendo.