Como evitar que o chgrp limpe o “bit setuid”?

8

Temos imagens Linux baseadas em RH; no qual tenho que "aplicar" alguns "arquivos especiais" para atualizá-los para a versão de desenvolvimento mais recente do nosso produto.

A pessoa que criou o arquivo concluiu que dentro da nossa imagem de base, algumas permissões estão erradas; então nos disseram para correr

sudo chgrp -R nobody /whatever

Nós fizemos isso; e mais tarde, quando nosso aplicativo está sendo executado, surgiram problemas obscuros.

O que eu achei mais tarde: a chamada para chgrp irá limpar as informações bit setuid em nossos binários dentro / whatever.

E o problema real é: alguns de nossos binários devem ter esse bit setuid definido para funcionar corretamente.

Para encurtar a história: existe uma maneira de executar esse comando "chgrp" sem matar meus bits setuid?

Eu apenas executei o seguinte no meu Ubuntu local; levando ao mesmo resultado:

mkdir sticky
cd sticky/
touch blub
chmod 4755 blub 
ls -al blub 

-> mostra o nome do arquivo com fundo vermelho -> sim, sim, setuid

chgrp -R myuser .
ls -al blub 

-> mostra o nome do arquivo sem fundo vermelho -> setuid desapareceu

GhostCat
fonte
1
O 4XXXbit é chamado bit setuid ( s), não pegajoso. Pegajosa é o tbit e seu objetivo é um pouco diferente: en.wikipedia.org/wiki/Sticky_bit
Zuazo
2
(1) Você está definindo o setuidbit, não o stickybit. (2) Não limpar o setuidbit quando você faz chgrpou chownseria um problema de segurança.
Satō Katsura
1
Esse comportamento muda entre distribuições. Mas, como explicado aqui , a alteração do bit setuid depende do comportamento subjacente do syscall.
Zuazo 30/09/16
Obrigado a todos. Você está correto, isso é sobre o bit setuid! Obrigado pela ajuda. E eu também aceito que isso é "funciona como projetado". Agora eu só preciso encontrar a maneira mais sensata de fazer o que precisa ser feito sem matar esses bits. Considero usar o gefacl para criar um despejo de texto, refazer a configuração do texto e aplicar esse. Isso deve me dar controle total sobre o que vai acontecer.
GhostCat 30/09/16

Respostas:

7

Se você deseja implementar seu chgrp -R nobody /whateverenquanto retém o bit setuid, pode usar estes dois findcomandos

find /whatever ! -type l -perm -04000 -exec chgrp nobody {} + \
                                      -exec chmod u+s {} +
find /whatever ! -type l ! -perm -04000 -exec chgrp nobody {} +

A find ... -perm 04000opção seleciona arquivos com o conjunto de bits setuid. O primeiro comando aplica oe, em chgrpseguida, a chmodpara restabelecer o bit setuid que foi eliminado. O segundo se aplica chgrpa todos os arquivos que não possuem um bit setuid.

De qualquer forma, você não deseja chamar chgrpou chmodusar links simbólicos, pois isso afetaria seus destinos, daí o ! -type l.

roaima
fonte
Observe que chgrptambém limpa o bit setgid (e os recursos no Linux) que também podem precisar ser restaurados.
Stéphane Chazelas
@ StéphaneChazelas você está certo, mas como ninguém mencionou o setgid, não me preocupei em fornecer uma solução para isso. A solução é trivialmente extensível, embora, com um terceirofind
roaima
Bem, não pode ser uma terceira descoberta, você teria que cobrir os casos u + g, u sozinho, g sozinho. De qualquer forma, você deve conseguir fazer isso em uma findchamada. Eu não gosto das longas linhas no SE quando você precisa rolar o texto. Minha adição do! tipo eu fiz isso ultrapassar os limites
Stéphane Chazelas 30/09
Bem, pode ser difícil fazer uma findabordagem -exec +confiável se isso acabar dividindo o chmod/ chgrps em várias invocações.
Stéphane Chazelas
1
Na verdade, acho que find . ! -type l -exec chgrp nobody {} + \( -perms -6000 -exec chmod gu+s {} + -o -perms -4000 -exec chmod u+s {} + -o -perms -2000 -exec chmod g+s {} + \)deve ficar bem. Como as chgrpcorrespondências para mais arquivos, para cada arquivo, devem ser feitas antes dos chmod.
Stéphane Chazelas
5

A limpeza de bits SUID e SGID em chgrp(ou chown) é perfeitamente razoável. É uma medida de segurança para evitar problemas de segurança. Para SGID (em executáveis, eu presumo) significa executar este programa com um grupo efetivo do proprietário do grupo .

Se você alterar o proprietário do grupo, em termos de segurança e controle de acesso, isso é algo completamente diferente, ou seja, em vez de executar com o grupo efetivo, uvwo programa agora será executado com o grupo efetivo xyz.

Portanto, você deve restaurar o bit SUID ou SGID explicitamente na mudança de propriedade.

Adendo: sob a alegação de que chgrp (ou chown) deve apenas limpar o SGID (ou SUID, resp.)

Ao chowning ou chgrping, você altera a configuração de segurança de um executável, e esse é um motivo suficiente para limpar quaisquer atributos de elevação de privilégio. O poder do Unix vem da simplicidade conceitual, e a segurança do Unix já é bastante complicada. Para esse fim, remover o SUID e o SGID em qualquer mudança de propriedade é simplesmente uma rede de segurança - afinal, na história do Unix / Linux, havia algumas vulnerabilidades devido a configurações equivocadas de SUID ou SGID.

Portanto, não há uma razão mais profunda pela qual o Unix se comporte dessa maneira, é apenas uma decisão de design conservadora.

contra-modo
fonte
1
Isso explica perfeitamente porque a mudança de proprietário limpa o bit SUID e a mudança de grupo limpa o bit SGID. Mas a pergunta é sobre o bit SUID durante uma operação de alteração de grupo que não afeta o usuário sob o qual o SUID é executado. Portanto, tem que haver uma explicação diferente.
Ben Voigt
1
@ BenVoigt: explica muito bem. Tanto o chown quanto o chgrp chamam o syscall chown (), que limpa suid e sgid em arquivos regulares, não importa o quê.
Joshua
1
@ Josué: Essa é uma descrição. A explicação é "para evitar o caso de que, em vez de executar com grupo efetivo, uvwo programa agora seja executado com grupo efetivo xyz", mas isso não se aplica ao caso em discussão.
Ben Voigt
Faz. Ao alterar chownou chgrpalterar a configuração de segurança, esse é um motivo suficiente para limpar os atributos de elevação de privilégio. Há grandes chances de que isso atinja os incautos.
countermode
4

A limpeza do bit setuid, setgid(pelo menos no Linux) em não-diretórios é feita pelo kernel na chown()chamada do sistema feita por chgrp, não por chgrpsi só. Portanto, a única maneira é restaurá-lo posteriormente.

Ele também limpa os recursos de segurança.

Então, no GNU Linux:

chown_preserve_sec() (
  newowner=${1?}; shift
  for file do
    perms=$(stat -Lc %a -- "$file") || continue
    cap=$(getfattr -m '^security\.capability$' --dump -- "$file") || continue
    chown -- "$newowner" "$file" || continue
    [ -z "$cap" ] || printf '%s\n' "$cap" | setfattr --restore=-
    chmod -- "$perms" "$file"
  done
)

E execute (as root):

chown_preseve_sec :newgroup file1 file2...

para alterar o grupo enquanto tenta preservar as permissões.

Recursivamente, você pode fazer:

# save permissions (and ACLs). Remove the "# owner" and "# group" lines
# to prevent them being restored!
perms=$(getfacl -RPn . | grep -vE '^# (owner|group): ')
# save capabilities
cap=$(getfattr -Rhm '^security\.capability$' --dump .)

chgrp -RP nobody .

# restore permissions, ACLs and capabilities
printf '%s\n' "$perms" | setfacl --restore=-
[ -z  "$cap" ] || printf '%s\n' "$cap" | setfattr -h --restore=-

(tudo isso assumindo que nada está atrapalhando os arquivos ao mesmo tempo).

Stéphane Chazelas
fonte
1

Como de costume na administração, existem muitos caminhos a percorrer.

A solução que eu coloquei foi assim:

cd /home/me
getfacl -R /whatever > whatever-permissions.org 2> /dev/null

# A) change lines starting with      # group: root
# to                                 # group: whatineed
sed 's/^# group: root/# group: whatineed/g' whatever-permissions.org > whatever-permissions.new

# B) change lines with               group::x.y
# to                                 group::xwy
# (where x, y mean: whatever was there before)
sed 's/^group::\(.\).\(.\)/group::\1w\2/g' whatever-permissions.new > whatever-permissions.new

cd /
setfacl --restore /home/me/whatever-permissions.new
GhostCat
fonte