Членство в группах и процессы setuid / setgid

10

Процессы, которые де-эскалируют привилегии через setuid()и setgid(), кажется, не наследуют членство в группах установленного ими uid / gid.

У меня есть серверный процесс, который должен быть выполнен от имени пользователя root, чтобы открыть привилегированный порт; после этого он де-эскалирует к определенному непривилегированному uid / gid, 1 - например, к пользователю foo(UID 73). Пользователь fooявляется членом группы bar:

> cat /etc/group | grep bar
bar:x:54:foo

Следовательно, если я войду в систему как foo, я могу прочитать файл /test.txtс этими характеристиками:

> ls -l /test.txt
-rw-r----- 1 root bar 10 Mar  8 16:22 /test.txt

Тем не менее, следующая C-программа (компилируется std=gnu99) при запуске root:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main (void) {
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}   

Всегда сообщает, что в доступе отказано . Я полагаю, что это связано с тем, что это процесс, не связанный с входом в систему, но он вроде подколенного сухожилия, как должны работать разрешения.


1. Что часто является SOP для серверов, и я думаю, что должен быть способ обойти это, поскольку я нашел сообщение о том, что кто-то делает это с apache - apache был добавлен в аудиогруппу и, очевидно, может затем использовать звуковую систему. Конечно, это, скорее всего, происходит в форке, а не в исходном процессе, но на самом деле в моем контексте дело обстоит так же (это дочерний процесс, разветвленный после вызова setuid).

лютик золотистый
источник
Переключите setuid()/ setgid()вызовы вокруг.
vonbrand
@vonbrand ROTFL Я думал, что там меня ждет лицевая маска, но результат тот же, поэтому я отредактирую вопрос, чтобы убрать красную сельдь.
Златовласка
1
Если вы используете setgid(54)вместо setgid(73)(как в /etc/groupsгруппе barесть gid 54), это работает?
lgeorget
@lgeorget Конечно, но это побеждает цель. Процесс нуждается в своем собственном GID по другим причинам, и аналогичным образом эти файлы должны иметь разрешения, которые они имеют. Вот почему членство во множественном числе групп необходимо - например, что если у вас есть два пользователя, которые должны сделать это. Обратите внимание, что вы не можете setuid()снова после того, как вы это сделаете ... но, хммм ... я думаю, что вы можете с seteuid()...
Златовласка
1
Мой вопрос состоял в том, чтобы убедиться, что где-то не было другой скрытой тонкой проблемы. :-)
lgeorget

Ответы:

14

Проблема заключается в том, что setuidи setgid не является достаточным , чтобы дать вашему процессу все полномочия, необходимые. Полномочия процесса зависят от

  • его UID
  • его GID
  • его дополнительные группы
  • его возможности.

Смотрите, man 7 credentialsчтобы получить более подробный обзор. Итак, в вашем случае проблема заключается в том, что вы правильно установили UID и GID, но не устанавливаете дополнительные группы процесса. И у группы barесть GID 54, а не 73, поэтому он не распознается как группа, в которой находится ваш процесс.

Ты должен сделать

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <grp.h>

int main (void) {
    gid_t supplementary_groups[] = {54};

    setgroups(1, supplementary_groups);
    setgid(73);
    setuid(73);
    int fd = open("/test.txt", O_RDONLY);
    fprintf(stderr,"%d\n", fd);
    return 0;
}  
lgeorget
источник
1
Это был интересный вопрос, который заслуживает большего количества голосов, потому что он может быть полезен для многих людей. :-)
lgeorget
Так что у меня была похожая проблема с последовательными портами. Я реализовал это для dialoutгруппы, и это сработало впервые.
TL8
0

ОК, немного побродил по сети. Сначала я думал, что APUE будет содержать все ответы, но ошибся. И моя копия (старая редакция) в работе, так что ... Глава 5 Руководства по администрированию Unix и Linux выглядит многообещающе, но у меня ее нет (просто копия первых двух редакций, также в работе).

В маленьких ресурсах, которые я нашел (google для "unix daemon writing"), все говорится о важных шагах, таких как отсоединение от tty и т. Д. Но ничего о UID / GID. Как ни странно, даже обширная коллекция HOWTO на http://tldp.org, похоже, не содержит подробностей. Только excetion Джейсон Шорты Напишет Linux Daemon - часть I . Полную информацию о том, как работает SUID / SGID и все эти беспорядки, можно найти в демоверсии SUID Чена, Вагнера и Дина (статья в USENIX 2002). Но будьте осторожны, у Linux есть дополнительный UID, FSUID (см. Замечания по совместимости Unix от Wolter : Функции настройки UID для обсуждения).

Демонизация процесса определенно не для слабонервных. Общие соображения безопасности даны в документе « Безопасное программирование D. Wheeler для Linux и Unix HOWTO - Создание безопасного программного обеспечения» . Systemd обещает упростить большую часть этого (и, таким образом, уменьшить пространство для ошибок, которые приводят к проблемам безопасности), см. Руководство к демону .

vonbrand
источник
1
Вопрос не в демонизации. Вы перепутали бит SUID (давая процессу полномочия владельца своего исполняемого файла) setuid(), который позволяет процессу произвольно изменять свой UID. SUID обычно предназначен для разрешения эскалации разрешений (непривилегированный -> привилегированный), тогда как setuid()может делать только обратное.
Златовласка