2010-02-16 2 views
11

Я пытаюсь сделать безопасную вещь и имею программу, которая должна запускаться от имени root, чтобы отбрасывать ее привилегии, когда она им не нужна. Это хорошо работает, если I chmod мой двоичный код с битом SUID и сделать его принадлежащим root, так как теперь у меня есть UID = некоторый пользователь и EUID = root, поэтому я могу использовать seteuid(0) и seteuid(getuid()), чтобы соответственно повышать и удалять права администратора.Как использовать setuid() от root, чтобы стать пользователем, с возможностью снова стать root?

Но если я использую sudo вместо установки SUID, тогда UID == EUID == 0, и поэтому вызов seteuid(getuid()) не будет иметь никакого эффекта. И я не могу просто изменить UID на какое-то значение от какого-то случайного пользователя, так как на странице пользователя setuid() четко указано, что если он вызывается из программы, запущенной с правами root, то теряет привилегии навсегда, не надеясь вернуть их.

Итак, как мне заставить свою программу временно потерять свои привилегии при запуске с использованием sudo?

+0

Вам нужно вернуться к UID пользователя, который управлял 'sudo', или просто случайным, менее привилегированным пользователем? –

+0

Я соглашусь на «никто». но если вы знаете простой способ получить sudo caller, мне интересно. – Florian

+3

meh, это просто, просто нужно 'getenv (" SUDO_UID ")'. – Florian

ответ

10

seteuid(some random uid), чтобы отказаться от привилегий, seteuid(0), чтобы вернуть их, когда работает как root.

+3

Конечно, это оставляет проблему получения исходного UID пользователя, который назвал 'sudo' - если OP должен вернуться к этому пользователю? –

+0

Конечно, есть шанс, что случайный UID, который вы переключаете, просто является идентификатором UID sysadmin. – immibis

+0

sudo создает переменные среды, содержащие UID и GID вызывающего пользователя. Вы можете переключиться на «никто», прочитав переменную и переключитесь на этого пользователя. Я не рекомендую читать переменные среды как root. «nobody» - ограниченная учетная запись, присутствующая в большинстве систем unix. – wheredidthatnamecomefrom

3

Не прямой ответ, просто хотел бы указать вам на идею privilege separation. Вот отличный presentation основатель OpenBSD Тео де Раадт.

6

Похоже seteuid (х) должны работать, чтобы упасть и вновь поднять privs ...

$ cat > t12.c 
#include <stdio.h> 
#include <unistd.h> 

void p(void) { printf("euid=%4d uid=%4d\n", geteuid(), getuid()); } 

int main(void) { p(); seteuid(100); p(); seteuid(0); p(); return 0; } 
$ cc -Wall t12.c 
$ sudo chown root a.out && sudo chmod 4555 a.out 
$ sudo ./a.out 
euid= 0 uid= 0 
euid= 100 uid= 0 
euid= 0 uid= 0 
$ ./a.out 
euid= 0 uid= 501 
euid= 100 uid= 501 
euid= 0 uid= 501 
$ 
+0

Как вы убедитесь, что uid = 100 не входит в группу sudoers? – dashesy

+0

Это важно только для самого судо. Единственная специальная привилегия, предоставляемая грантами группы sudoers, - это возможность использовать команду sudo. Это не делает идентификатор пользователя root доступным. – wheredidthatnamecomefrom

1

вилка(), прежде чем упасть привилегии. Подождите в родительской задаче до тех пор, пока не будет выполнен дочерний элемент с ограниченными правами, а затем возобновите работу с родителем с корнем.

seteuid не переносится для всех узлов и имеет другие недостатки.

Смежные вопросы