Ubuntu - чи може користувач без корінців запускати процес у в'язниці chroot?


18

Чи можливо для некористувального користувача запустити процес chroot на Ubuntu?


Цей старий потік FreeBSD охоплює те саме запитання: list.freebsd.org/pipermail/freebsd-security/2003-April/… Коротка відповідь: Ні, ви не можете запустити процес як root у не-кореневій в'язниці chroot.
Девід Гаррісон

в'язниці chroot характерні лише для bsd. chroot в Linux не є в'язницею. Востаннє я перевірив, що неможливо хронізувати як користувача.
ксенотеррацид

1
@xenoterracide Ув'язнення є специфічними для BSD, однак chroot у спільноті Linux широко відомий як "в'язниця chroot". Це зовсім заплутано.
pehrs

2
Що ви намагаєтеся зробити і чому? Є такі інструменти, як фейкшрот та шроут, які дозволяють забезпечити ефективну альтернативу залежно від ваших потреб.
Зоредаче

Було також більше пов'язаних обговорень на тему: Як "ув’язнити" процес, не виконуючи корінь? з переліченими більш робочими або орієнтовними підходами до вирішення цього завдання.
imz - Іван Захарящев

Відповіді:


12

У Linux системний виклик chroot (2) може здійснюватися лише привілейованим процесом. Можливість, яку потребує процес, становить CAP_SYS_CHROOT.

Причина, по якій ви не можете хронізуватися як користувач, досить проста. Припустимо, у вас встановлена ​​програма, така як sudo, яка перевіряє / etc / sudoers, якщо вам дозволяють щось робити. Тепер покладіть його в chroot chroot із власними / etc / sudoers. Раптом у вас моментальна ескалація привілеїв.

Можна створити програму, щоб хронізувати себе та запустити її як встановлений процес, але це, як правило, вважається поганим дизайном. Додаткова безпека chroot не мотивує проблеми безпеки із налаштуванням.


3
З новими можливостями просторів імен у Linux, можливо, можливо створити (скасувати) новий простір імен "користувач", де був би "вбудований" користувач root, і виконати chrootйого.
imz - Іван Захарящев

1
@ imz - IvanZakharyaschev Ви абсолютно правильні, і я сподіваюся, що ви не заперечуєте проти того, що я взяв на себе сміливість написати це як легко перевіряема відповідь.
hvd

@hvd Чудово! Це повинно бути дуже корисним, оскільки воно демонструє, як використовувати нові незнайомі функції Linux за допомогою конкретних команд.
imz - Іван Захарящев

6

@ imz - ІванЗахарящев коментує відповідь pehrs про те, що це можливо через введення просторів імен, але це не перевірено і не було розміщено як відповідь. Так, це дійсно дає можливість користувачеві, котрий не має права root, використовувати chroot.

Дано статично пов'язану dash, статично пов'язану busyboxта запущену bashоболонку, що працює як некоренева:

$ 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

Ідентифікатор кореневого користувача в цьому просторі імен відображається на ідентифікатор некорінного користувача поза цим простором імен, і навпаки, тому система показує файли, що належать поточному користувачеві, як власник ідентифікатора користувача 0. Регулярний ls -al root, без unshare, робить показувати їх як власність поточного користувача.


Примітка: загальновідомо, що процеси, які здатні використовувати chroot, здатні вибиватися з a chroot. Оскільки unshare -rнадасть chrootдозволи звичайному користувачеві, це було б ризиком для безпеки, якби це було дозволено всередині chrootсередовища. Дійсно, це не дозволено, і не вдається:

unshare: unshare failed: Операція не дозволена

яка відповідає документації, що не використовується (2) :

EPERM (з Linux 3.9)

CLONE_NEWUSER був вказаний у прапорах, а абонент знаходиться у середовищі chroot (тобто коренева директорія абонента не відповідає кореневій директорії простору імен версії, в якій він знаходиться).


Запуск pivot_root у просторі імен монтування має подібний ефект до chroot, але уникає конфлікту з просторами імен користувачів.
Тімоті Болдуін

1
Можна вийти з chroot або змонтувати простір імен, спустившись у / proc, якщо їх процес є зовнішнім з таким самим UID у тому самому або дочірньому PID та просторі імен користувачів.
Тімоті Болдуін

2

У ці дні ви хочете подивитися на LXC (Linux Containers) замість chroot / BSD. Це десь між chroot і віртуальною машиною, що дає вам багато контролю над безпекою і загальної налаштованості. Я вважаю, що все, що вам потрібно, щоб запустити його як користувач - це бути членом групи, яка володіє необхідними файлами / пристроями, але також можуть бути залучені можливості / системні дозволи. У будь-якому випадку це має бути дуже придатним, оскільки LXC є нещодавним, довго після того, як до ядра Linux було додано SELinux тощо.

Також майте на увазі, що ви можете просто писати скрипти як root, але надавати користувачам безпечний дозвіл на запуск цих сценаріїв (без пароля, якщо вам подобається, але переконайтеся, що сценарій захищений) за допомогою sudo.


1

Поєднання fakeroot / fakechroot дає змогу chroot для простих потреб, таких як створення архівів tar, де файли, як видається, належать root. Сторінка Fakechroot - це http://linux.die.net/man/1/fakechroot .

Ви не отримуєте жодного нового дозволу, але якщо у вас є каталог (наприклад, підроблений дистрибутив) перед тим, як викликати його

fakechroot fakeroot chroot ~/fake-distro some-command

тепер шукайте якусь команду, як ви root, і володієте всім у підробці distro.


Це гарна ідея, але, схоже, справляти символьні посилання непередбачувано. Моє ~/fake-distroвикористання BusyBox, які символічні посилання ls, mvі інші загальні утиліти для /bin/busybox. Якщо я чітко телефоную /bin/busybox mv ..., все працює, але якщо я дзвоню, /bin/mv ...я отримую sh: /bin/mv: not found. Встановлення export FAKECHROOT_EXCLUDE_PATH=/перед запуском фальшивки виправляє цей симптом, але потім він порушується на інших символьних посиланнях (наприклад /usr/bin/vim -> /usr/bin/vim.vim).
Ponkadoodle

можливо FAKECHROOT_EXCLUDE_PATH = /: / usr допоможе тоді?
sylvainulg

1

Здається, що з просторами імен користувачів можна насправді хронуватись без кореня. Ось приклад програми, яка демонструє, що це можливо. Я лише почав досліджувати, як працюють простори імен Linux, і тому я не зовсім впевнений, найкращий досвід чи цей код.

Зберегти як user_chroot.cc. Компілювати з g++ -o user_chroot user_chroot.cc. Використання є ./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;
    }
}

Я перевірив це на мінімальних коренях, згенерованих за допомогою мультистрапу (виконується як некореневий). Деякі системні файли, як /etc/passwdі /etc/groupsбули скопійовані з хост-корфів у гостьові корни.


Збій Failed to unshare user namespaceдля мене на Linux 4.12.10 (Arch Linux).
Ponkadoodle

@wallacoloo, можливо, змінить printf () на perror () і подивіться, яка фактична помилка. див. man7.org/linux/man-pages/man2/unshare.2.html, які коди помилок можуть бути результатом невдалого unshareвиклику. Ви також можете спробувати цю версію python, яка може мати кращі повідомлення про помилки: github.com/cheshirekow/uchroot
cheshirekow

1
Насправді @wallacoloo це здається, що арка вимикає непривітні простори імен користувачів у своїй збірці ядра: list.archlinux.org/pipermail/arch-general/2017-February/…
cheshirekow

0

Ні. Якщо я правильно пригадую, є щось, що робить chroot, що перешкоджає цьому. Я не пам'ятаю, що це було. Я досліджував це ще раз, коли возився з інструментом збирання Catalyst Gentoo (а chroot на gentoo - те саме, що chroot на ubuntu). Хоча можна було б це зробити і без пароля ... але такі речі залишаються в царині потенційних вразливих місць безпеки і обов'язково знаєте, що ви робите.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.