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


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


15
2018-04-25 08:50


origen


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
Las jaulas chroot son específicas para bsd. Un chroot en linux no es una cárcel. La última vez que lo comprobé no era posible chrootear como usuario. - xenoterracide
@xenoterracide Jails son específicas de BSD, pero chroot se conoce comúnmente como "chroot jail" en la comunidad de Linux. Está bastante confundido. - pehrs
¿Qué estás tratando de hacer y por qué? Existen herramientas como fakechroot y schroot que proporcionan una alternativa viable en función de sus requisitos. - Zoredache
También hubo más discusión relacionada en ¿Cómo “encarcelar” un proceso sin ser root? con más enfoques de trabajo o tentativos para resolver esta tarea enumerados. - imz -- Ivan Zakharyaschev


Respuestas:


En linux chroot (2) La llamada al sistema solo puede realizarse mediante un proceso que tenga privilegios. La capacidad que necesita el proceso es CAP_SYS_CHROOT.

La razón por la que no puedes chrootear como usuario es bastante simple. Supongamos que tiene un programa setuid como sudo que verifica / 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 activarse y ejecutarse 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.


10
2018-04-25 19:38



Con las nuevas posibilidades de espacios de nombres en Linux, tal vez sea posible crear (dejar de compartir) un nuevo espacio de nombres de "usuario", donde habría un usuario root "incorporado", y realizar chroot entonces. - imz -- Ivan Zakharyaschev
@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 de Linux desconocidas con comandos concretos. - imz -- Ivan Zakharyaschev


@imz - IvanZakharyaschev comenta sobre la respuesta de pehrs de que puede ser posible con la introducción de espacios de nombres, pero esto no se ha probado y publicado como respuesta. Sí, eso hace posible que un usuario no root use chroot.

Dado un enlace estático dash, y un enlace estático busybox, y una carrera bash shell ejecutándose 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, por lo que el sistema muestra los archivos que pertenecen al usuario actual como propiedad de la ID de usuario 0. A ls -al root, sin unshare, los muestra como propiedad del usuario actual.


Nota: es bien sabido que los procesos que son capaces de usar chroot, son capaces de salir de un chroot. Ya que unshare -r otorgaría chroot permisos para un usuario ordinario, sería un riesgo de seguridad si se permitiera dentro de un chroot ambiente. De hecho, no está permitido, y falla con:

no compartir: error de no compartir: operación no permitida

que coincide con el no compartir (2) documentación (disculpas por la extraña negrita, pero eso es lo que parece):

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).


5
2017-12-02 19:25



La ejecución de pivot_root en un espacio de nombres de montaje tiene un efecto similar al de chroot pero evita el conflicto con los espacios de nombres de usuarios. - Timothy Baldwin
Uno puede escapar de un chroot o montar un espacio de nombres descendiendo a / proc si se trata de un proceso externo con el mismo UID en el mismo o PID secundario y espacios de nombres de usuario. - Timothy Baldwin


En estos días, debes estar buscando LXC (Contenedores de Linux) en lugar de chroot / BSD jail. Está en algún lugar entre un chroot y una máquina virtual, lo que le brinda mucho control de seguridad y capacidad de 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 de sistema involucrados. De cualquier manera, debería ser muy factible, ya que LXC es bastante reciente, mucho después de que se haya agregado SELinux, etc., al kernel de Linux.

Además, tenga en cuenta que solo puede escribir scripts como root, pero darles permiso a los usuarios para ejecutar esos scripts (sin una contraseña si lo desea, pero asegúrese de que el script sea seguro) usando sudo.


2
2018-04-26 01:09





La combinación de fakeroot / fakechroot proporciona un simulacro de chroot para necesidades simples, como producir 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 (por ejemplo, fake-distro) antes de invocar

fakechroot fakeroot chroot ~/fake-distro some-command

ahora busca algún comando como si fueras root y poseyes todo dentro de la falsa distro.


1
2017-07-06 12:14



Esta es una buena idea, pero parece manejar enlaces simbólicos de forma impredecible. Mi ~/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 ... yo obtengo sh: /bin/mv: not found. Ajuste export FAKECHROOT_EXCLUDE_PATH=/ antes de ejecutar fakechroot corrige ese síntoma, pero luego se rompe en otros enlaces simbólicos (por ejemplo, /usr/bin/vim -> /usr/bin/vim.vim). - Ponkadoodle
tal vez FAKECHROOT_EXCLUDE_PATH = /: / usr ayudaría, entonces? - sylvainulg


Parece que con espacios de nombres de usuario es posible chroot sin root. Aquí hay un programa de ejemplo que demuestra que es posible. Acabo de comenzar a explorar cómo funcionan los espacios de nombres de Linux, por lo que 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 mínimo de rootfs generados con multistrap (ejecutado como no root). Algunos archivos del sistema como /etc/passwd y /etc/groups se copiaron desde el host rootfs al host rootfs.


1
2017-10-26 20:17



Falla en Failed to unshare user namespace Para mí en Linux 4.12.10 (Arch Linux). - Ponkadoodle
@wallacoloo quizás modifique printf () para perror () y vea cuál fue el error real. Referirse a man7.org/linux/man-pages/man2/unshare.2.html ¿Por qué códigos de error pueden resultar de un fracaso? unshare llamada. También puedes probar esta versión de python que podría tener un mejor mensaje de error: github.com/cheshirekow/uchroot - cheshirekow
En realidad, @wallacoloo suena como que el arco deshabilita los espacios de nombres de usuarios no registrados en su compilación del kernel: lists.archlinux.org/pipermail/arch-general/2017-February/… - cheshirekow


No. Si recuerdo correctamente, hay algo del 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 chroot en gentoo es lo mismo que chroot en ubuntu). Aunque sería posible hacerlo sin una contraseña ... pero esas cosas se dejan al alcance de las posibles vulnerabilidades de seguridad y se aseguran de que sepa lo que está haciendo.


0
2018-04-25 10:13