Ubuntu - l'utente non root può eseguire il processo nel carcere chroot?


18

È possibile per un utente non root eseguire un processo chroot su Ubuntu?


Questo vecchio thread di FreeBSD copre la stessa domanda: lists.freebsd.org/pipermail/freebsd-security/2003-April/… Risposta breve: No, non puoi eseguire un processo come root all'interno di una prigione chroot non root.
David Harrison,

le jail chroot sono specifiche di bsd. un chroot in linux non è una prigione. L'ultima volta che ho controllato non era possibile chroot come utente.
xenoterracide

1
Le jail @xenoterracide sono specifiche di BSD, ma chroot è comunemente noto come "jroot chroot" nella comunità Linux. È abbastanza confuso.
pehrs

2
Cosa stai cercando di fare e perché? Esistono strumenti come fakechroot e schroot che offrono un'alternativa praticabile a seconda delle tue esigenze.
Zoredache,

C'è stata anche una discussione più correlata su Come "imprigionare" un processo senza essere root? con più approcci di lavoro o tentativi per risolvere questo compito elencati.
imz - Ivan Zakharyaschev,

Risposte:


12

Su Linux la chiamata di sistema chroot (2) può essere effettuata solo con un processo privilegiato. La capacità di cui il processo ha bisogno è CAP_SYS_CHROOT.

Il motivo per cui non è possibile eseguire il chroot come utente è piuttosto semplice. Supponiamo di avere un programma setuid come sudo che controlla / etc / sudoers se ti è permesso fare qualcosa. Ora mettilo in un chroot chroot con il tuo / etc / sudoers. All'improvviso hai un'escalation di privilegi istantanea.

È possibile progettare un programma per chroot stesso ed eseguirlo come un processo setuid, ma questo è generalmente considerato una cattiva progettazione. La sicurezza aggiuntiva del chroot non motiva i problemi di sicurezza con il setuid.


3
Con le nuove possibilità degli spazi dei nomi in Linux, forse è possibile creare (annullare la condivisione) un nuovo spazio dei nomi "utente", dove ci sarebbe un utente root "incorporato", e chrootpoi eseguire .
imz - Ivan Zakharyaschev,

1
@ imz - IvanZakharyaschev Hai assolutamente ragione, e spero che non ti dispiaccia se mi sono preso la libertà di scriverlo come una risposta facilmente verificabile.
hvd,

@hvd Ottimo! Deve essere molto utile, perché dimostra come utilizzare le nuove funzionalità di Linux sconosciute con comandi concreti.
imz - Ivan Zakharyaschev,

6

@ imz - IvanZakharyaschev commenta la risposta di Pehrs che potrebbe essere possibile con l'introduzione di spazi dei nomi, ma questo non è stato testato e pubblicato come risposta. Sì, ciò rende effettivamente possibile per un utente non root usare chroot.

Dato uno staticamente collegato dash, uno staticamente collegato busyboxe una bashshell in esecuzione in esecuzione come 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

L'ID utente root in quel namespace è mappata non root ID utente all'esterno di detto spazio, e viceversa, motivo per cui i file di sistema mostra proprietà dell'utente corrente come proprietà di ID utente 0. Un regolare ls -al root, senza unshare, fa mostrarli come di proprietà dell'utente corrente.


Nota: è noto che i processi in grado di utilizzare chrootsono in grado di uscire da a chroot. Poiché unshare -rconcederebbe le chrootautorizzazioni a un utente normale, sarebbe un rischio per la sicurezza se ciò fosse consentito all'interno di un chrootambiente. In effetti, non è consentito e non riesce con:

unshare: unshare non riuscita: operazione non consentita

che corrisponde alla documentazione unshare (2) :

EPERM (dal Linux 3.9)

CLONE_NEWUSER è stato specificato nei flag e il chiamante si trova in un ambiente chroot (ovvero, la directory principale del chiamante non corrisponde alla directory principale dello spazio dei nomi di mount in cui risiede).


L'esecuzione di pivot_root in uno spazio dei nomi mount ha un effetto simile a chroot ma evita il conflitto con gli spazi dei nomi utente.
Timothy Baldwin,

1
Si può evitare un chroot o montare lo spazio dei nomi scendendo in / proc se il loro è un processo esterno con lo stesso UID nello stesso PID o spazi dei nomi utente o utente.
Timothy Baldwin,

2

In questi giorni, vuoi guardare LXC (Linux Containers) invece di chroot / BSD jail. È a metà strada tra un chroot e una macchina virtuale, offrendoti molto controllo di sicurezza e configurabilità generale. Credo che tutto ciò di cui hai bisogno per eseguirlo come utente sia essere un membro del gruppo che possiede i file / dispositivi necessari, ma potrebbero esserci anche capacità / autorizzazioni di sistema. Ad ogni modo, dovrebbe essere molto fattibile, dato che LXC è abbastanza recente, molto tempo dopo che SELinux ecc. È stato aggiunto al kernel Linux.

Inoltre, tieni presente che puoi semplicemente scrivere script come root ma dare agli utenti l'autorizzazione sicura per eseguirli (senza una password se vuoi, ma assicurati che lo script sia sicuro) usando sudo.


1

La combinazione di fakeroot / fakechroot fornisce un simulacro di chroot per esigenze semplici come la produzione di archivi tar in cui i file sembrano essere di proprietà di root. La manpage di Fakechroot è http://linux.die.net/man/1/fakechroot .

Tuttavia, non si ottiene alcuna nuova autorizzazione, ma se si possiede una directory (ad esempio fake-distro) prima di invocare

fakechroot fakeroot chroot ~/fake-distro some-command

ora cerca qualche comando come se fossi root e possiedi tutto in fake-distro.


Questa è una bella idea, ma sembra gestire imprevedibilmente i link simbolici. Il mio ~/fake-distrousi busybox, che link simbolici ls, mve altre utilità comuni /bin/busybox. Se chiamo esplicitamente /bin/busybox mv ..., le cose funzionano, ma se chiamo /bin/mv ...ottengo sh: /bin/mv: not found. L'impostazione export FAKECHROOT_EXCLUDE_PATH=/prima di eseguire fakechroot corregge quel sintomo, ma poi si interrompe su altri collegamenti simbolici (ad es /usr/bin/vim -> /usr/bin/vim.vim.).
Ponkadoodle,

forse FAKECHROOT_EXCLUDE_PATH = /: / usr sarebbe d'aiuto, allora?
sylvainulg,

1

Sembra che con gli spazi dei nomi utente sia possibile chroot senza root. Ecco un programma di esempio che dimostra che è possibile. Ho solo iniziato a esplorare come funzionano gli spazi dei nomi di Linux e quindi non sono del tutto sicuro se questo codice sia la migliore pratica o meno.

Salva come user_chroot.cc. Compila con g++ -o user_chroot user_chroot.cc. L'uso è ./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;
    }
}

Ho provato questo su un minimo rootfs generato con multistrap (eseguito come non root). Alcuni file di sistema gradiscono /etc/passwde /etc/groupssono stati copiati dai rootfs host ai rootfs guest.


Non riesce Failed to unshare user namespaceper me su Linux 4.12.10 (Arch Linux).
Ponkadoodle,

@wallacoloo forse modifica printf () in perror () e guarda qual è stato il vero errore. fare riferimento a man7.org/linux/man-pages/man2/unshare.2.html per quali codici di errore possono derivare da una unsharechiamata non riuscita . Puoi anche provare questa versione di Python che potrebbe avere una migliore messaggistica di errore: github.com/cheshirekow/uchroot
cheshirekow

1
In realtà @wallacoloo sembra che arch disabiliti gli spazi dei nomi utente non privilegiati nella sua build del kernel: lists.archlinux.org/pipermail/arch-general/2017-Fe febbraio
cheshirekow,

0

No. Se ricordo bene c'è qualcosa a livello di kernel che Chroot fa per impedirlo. Non ricordo cos'era quella cosa. L'ho studiato di nuovo quando si scherzava con lo strumento Catalyst Build di Gentoo (e un chroot su gentoo è lo stesso di un chroot su Ubuntu). Anche se sarebbe possibile farlo accadere senza un passwd ... ma tali cose sono lasciate al regno delle potenziali vulnerabilità della sicurezza e assicurandosi di sapere cosa stai facendo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.