Eliminar privilégios do processo

12

Eu tenho um processo que é iniciado por um damon em execução como root, agora eu quero "rebaixar" os privilégios desse processo para os do usuário médio. Isso é possível? Se sim, como?

PS: rodando unix em um mac

Samantha Catania
fonte

Respostas:

5

O próprio processo deve chamar setuid (2). Você também deve investigar a execução dentro do chroot (8), se ainda não estiver. Até onde eu sei, não há como o root alterar o uid de outro processo.

Se o motivo de você executá-lo como raiz é vincular portas, sugiro executá-lo como um usuário normal em uma porta superior e usando o ipfw (8) no OS X para encaminhar a porta 80/443 / etc para a porta superior:

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx

polinomial
fonte
Coloquei setuid (uid) no meu programa que é executado como raiz, mas eu preciso que ele seja executado como um usuário normal e nada acontece ou seja, ele continua funcionando como root
Samantha Catania
Você provavelmente precisará capturar os erros (talvez esteja recebendo um EINVAL para o uid). Seu setuid improvável está quebrado na sua máquina, você pode verificar vendo se o apache está sendo executado como _www. Documentos do programador: developer.apple.com/library/mac/#documentation/Darwin/Reference/…
polynomial
você está certo, gera um erro de sintaxe do uid, mesmo que esteja correto. este é o formato correto setuid (500)?
Samantha Catania
Encontrei o problema: estava tentando executar o comando através do sistema (), mas apenas executei o comando que funcionava e resolvi o meu problema; thx pela ajuda
Samantha Catania
Não. Esse não é um bom conselho: ligar setuid()sozinho não é absolutamente suficiente.
Nicholas Wilson
13

sudo tcpdump -Z usa initgroups (3), setgid (2) e setuid (2) para eliminar os privilégios de root de seu próprio processo.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}
phron
fonte
2
Corrigir. initgroups, setgid, setuid(Finalmente!) É precisamente o paradigma direito sobre unix, e deve sempre ser seguido. Além disso, uma função responsável "droproot" verifica se seu uid e gid foram realmente configurados, mesmo que todas as três funções principais tenham retornado com êxito.
Nicholas Wilson
3

Você pode executar comandos como outros usuários usando su:

 su USERNAME -c COMMAND

Será executado COMMANDcom privilégios caiu para USER.


Observe que, por padrão, suusará o interpretador de shell do usuário de destino para executar o comando. Por outro lado, o comportamento padrão de sudoé tratar o programa COMMANDcomo independente, que é executado no ambiente atual. É claro que esses comportamentos padrão podem ser alterados com várias opções e variáveis ​​de ambiente.

rozcietrzewiacz
fonte
Parece suque não funcionará se USERNAME não tiver um shell definido (ou /bin/false) enquanto o sudo funcionar.
Aif
1
@Aif Se o usuário não tiver permissão para executar comandos interativos, o comportamento padrãosu refletirá isso. No entanto, sempre é possível substituir isso usando o -sswitch. Observe que o objetivo sué imitar o comportamento de um determinado usuário - que normalmente é influenciado por seu shell. Por outro lado, sudo(por padrão) ignoraria a configuração de shell do usuário de destino.
rozcietrzewiacz
Não, por favor, não execute as coisas usando um shell simplesmente para remover privilégios. Isso deixa muito o controle de um invasor, lendo vários arquivos de configuração que você não quer tocar.
Nicholas Wilson
2

Para eliminar privilégios, você precisa de um usuário não raiz para o qual. Então é apenas uma questão de mudar para esse usuário:

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

Observe que isso é feito dentro do próprio programa , e não em um script de wrapper. Muitos programas requerem privilégios de root para algum propósito específico (por exemplo, para vincular a uma porta de número baixo), mas não precisam de root depois disso. Portanto, esses programas serão iniciados como root, mas eliminarão os privilégios quando não forem mais necessários.

Se você não precisa de privilégios de root, simplesmente não o execute como root. Por exemplo:

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
tylerl
fonte
1
Observe que isso permite que o processo recupere os privilégios, se desejar! A setuidfunção define apenas o UID efetivo , não o UID real. Você deve usar setreuidse não quiser que o processo recupere os privilégios. (E o código acima não lida com privilégios suplementares grupo quer É adequado apenas para lançar código principalmente confiável..)
David Schwartz
O código de David Schwartz foi intencionalmente simplificado para mostrar o mecanismo usado.
tylerl
Para simplificar o código crítico de segurança, é preciso deixar bem claro que é isso que você está fazendo. E você deve dizer coisas como "é apenas uma questão de" quando não é.
David Schwartz
2
@ David Na verdade, setuid()define userids reais e salvos; você pode estar pensando seteuid(). Nem todos os sistemas possuem setreuid(), portanto, ele não pode ser usado em qualquer lugar. A semântica exata de setuid()é complicada, mas se você tiver o euid 0, poderá eliminar todos os privilégios de identificação de usuário tradicionais setuid(). A maior omissão nesta resposta é que initgroupsou setgroupsdeve ser chamada assim como setgide setuid, e que afirmações mais completas devem ser feitas no final.
Nicholas Wilson
0

Se você estiver executando um executável diferente, ou seja, você está chamando execveou outro execmembro da família de funções, talvez indiretamente através de uma função como systemor popen, e o processo filho deve ser executado sem privilégios desde o início, a maneira mais simples é obter um shell envolvido e chamada su. Aqui está uma visão geral de como o código pode parecer no Perl, mostrando as citações necessárias para:

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

Se o processo filho precisar iniciar como root, mas eliminar privilégios posteriormente, consulte o código nesta resposta , que ilustra como fazer o downgrade de privilégios em um processo.

Gilles 'SO- parar de ser mau'
fonte