Ubuntu: ¿puede el usuario no root ejecutar el proceso en chroot jail?


18

¿Es posible que un usuario no root ejecute un proceso chroot en Ubuntu?


Este viejo hilo de FreeBSD cubre la misma pregunta: lists.freebsd.org/pipermail/freebsd-security/2003-April/… Respuesta corta: No, no puede ejecutar un proceso como root dentro de una cárcel chroot no root.
David Harrison el

las cárceles chroot son específicas de bsd. un chroot en linux no es una cárcel. La última vez que verifiqué que no era posible hacer un chroot como usuario.
xenoterracide

1
@xenoterracide Las cárceles son específicas de BSD, pero chroot se conoce comúnmente como una "cárcel chroot" en la comunidad Linux. Está bastante confundido.
pehrs

2
¿Qué intentas hacer y por qué? Existen herramientas como fakechroot y schroot que brindan una alternativa viable según sus requisitos.
Zoredache

También hubo una discusión más relacionada en ¿Cómo "encarcelar" un proceso sin ser root? con más enfoques de trabajo o tentativos para resolver esta tarea en la lista.
imz - Ivan Zakharyaschev

Respuestas:


12

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.


3
Con las nuevas posibilidades de espacios de nombres en Linux, tal vez sea posible crear (no compartir) un nuevo espacio de nombres "usuario", donde habría un usuario raíz "incrustado", y chrootluego realizarlo .
imz - Ivan Zakharyaschev

1
@ imz - IvanZakharyaschev Tienes toda la razón, y espero que no te importe que me haya tomado la libertad de escribir eso como una respuesta fácilmente comprobable.
hvd

@hvd ¡Genial! Debe ser muy útil, ya que demuestra cómo usar las nuevas características desconocidas de Linux con comandos concretos.
imz - Ivan Zakharyaschev

6

@ 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 -rque otorgaría chrootpermisos 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).


Ejecutar pivot_root en un espacio de nombres de montaje tiene un efecto similar a chroot pero evita el conflicto con los espacios de nombres de usuario.
Timothy Baldwin

1
Se puede escapar de un espacio de nombres chroot o mount descendiendo a / proc si es un proceso externo con el mismo UID en el mismo PID o espacio de nombres de usuario.
Timothy Baldwin

2

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.


1

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.


Esta es una buena idea, pero parece manejar enlaces simbólicos de forma impredecible. My ~/fake-distrousa busybox, que enlaces simbólicos ls, mvy 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).
Ponkadoodle

quizás FAKECHROOT_EXCLUDE_PATH = /: / usr ayudaría, entonces?
sylvainulg

1

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/passwdy /etc/groupsfueron copiados de los rootfs del host en los rootfs invitados.


Failed to unshare user namespaceMe falla en Linux 4.12.10 (Arch Linux).
Ponkadoodle

@wallacoloo quizás modifique printf () a perror () y vea cuál fue el error real. consulte man7.org/linux/man-pages/man2/unshare.2.html para ver qué códigos de error pueden resultar de una unsharellamada fallida . También puede probar esta versión de Python que podría tener mejores mensajes de error: github.com/cheshirekow/uchroot
cheshirekow

1
En realidad, @wallacoloo parece que el arco deshabilita los espacios de nombres de usuario sin privilegios en su compilación del núcleo: lists.archlinux.org/pipermail/arch-general/2017-February/…
cheshirekow

0

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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.