eUID errado em '/ proc / PID / status' quando SETUID é usado

1

Enquanto fazia um desafio de guerra, me deparei com um problema com permissões. A informação dada por /proc/PID/status não está em adequação com as permissões que devem ser dadas ao processo.

Eu sou usuário user1. Eu deveria usar um programa que é SETUID:

-r-sr-x---  1 user2 user1       6297 Jun 20  2013 program

Portanto, ele deve ser executado com o UID efetivo do usuário2.

Estou interrompendo temporariamente o programa logo após o lançamento para evitar que ele seja encerrado:

~/program "test" &
PID=$!
kill -SIGSTOP $PID
echo $PID

Então, eu cat /proc/$PID/status e eu vejo:

Uid:    1003    1003    1003    1003
Gid:    1003    1003    1003    1003

Os IDs são:

$ id user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)
$ id user2
uid=1035(user2) gid=1035(user2) groups=1035(user2),1003(user1)

Dado o manual ( man 5 proc ), /proc/$PID/status deve fornecer Uid, Gid: Real, effective, saved set, and filesystem UIDs (GIDs).

Mas aqui, o processo tem o ID efetivo de user1, enquanto deve ter o ID efetivo de user2 .

Eu pensei que isso poderia ser porque eu parei o programa muito cedo, então eu tentei anexar gdb a ele, e continuar a execução até que ele realmente execute código da função main de program (as fontes são fornecidas) , mas o UID efetivo dado por /proc/$PID/status ainda é o de user1 e não de user2.

Estou sentindo falta de algo?

Editar: remover a origem do desafio, provavelmente não estou autorizado a publicá-lo.

    
por vmarquet 24.07.2015 / 10:25

2 respostas

3

É porque você é muito cedo, se você esperar até que os UIDs sejam alterados, seu processo será executado como user2 . Isso funcionou para mim:

./program "test" &
PID=$!
sleep 0.0005
kill -SIGSTOP $PID
grep ^Uid /proc/$PID/status

Outra tentativa é adicionar um atraso com usleep() e enviar o SIGSTOP mais tarde durante esse período. Então o programa é executado com user2 como uid efetivo. Você pode verificar isso, mas sem anexar com gdb ou strace . Muito provavelmente é algum tipo de linux kernel interna, que o processo precisa de algum tempo para mudar os UIDs.

Ao executar o processo a partir de um terminal, o execve() syscall é chamado; da manpage:

If the set-user-ID bit is set on the program file pointed to by filename, [...] and the calling process is not being ptraced, then the effective user ID of the calling process is changed to that of the owner of the program file.

Quando você anexar gdb ao processo, não verá o fluxo de user2 , porque você está ptrace do processo, conforme descrito na página de manual acima. Ou então você poderia anexar a um sudo -process e obter permissões de root.

No entanto, esse programa nunca recebe uma falha de segmentação ( SIGSEGV ), a menos que você force um com kill -SIGSEGV $PID . SE seu programm recebe uma SIGSEGV , a rotina launch_debugger() é chamada. Isso chamará um gdb e como argumento apenas o seu program binário sem nenhum argumento, o que substituirá o processo atual em execução. Portanto, no depurador teremos privilégios de user2 e, portanto, você pode fazer o que quiser lá, com as permissões de user2 .

Você pode, por exemplo, fazer o seguinte dentro de gdb :

(gdb) file bash
Reading symbols from /bin/bash...(no debugging symbols found)...done.
(gdb) run
Starting program: /bin/bash
user2@host:~$ id
uid=1035(user2) gid=1003(user1) groups=1035(user2),1003(user1)

Agora, considere o mesmo binário com um bit setuid e o proprietário é root.

    
por 24.07.2015 / 14:15
1

O programa está executando em um sistema de arquivos que honra o setuid bit nos arquivos ( mount -o nosuid )?

Se eu estivesse depurando isso, eu imprimiria a saída de getuid() e geteuid() na inicialização do programa, para ver se o setuid bit está sendo respeitado.

    
por 24.07.2015 / 12:24