A autenticação através de PAM pode ter êxito quando executa o cliente à mão e falhar com AUTH_FAILED assim que o systemd inicia o mesmo perfil. A palavra-passe não muda entre essas execuções; o que muda é o conjunto de restrições em torno do processo que faz a pergunta ao PAM. O PAM responde através de um helper cuja capacidade de alterar as suas próprias credenciais é exatamente o que uma unidade endurecida remove. Encontre esse helper e o limite de que ele precisa antes de tocar numa lista de capacidades.

unix_chkpwd é o binário que responde à pergunta do PAM

Com autenticação por palavra-passe local, o pam_unix raramente lê o ficheiro de hash. Executa o unix_chkpwd, que as distribuições instalam com setuid root ou setgid shadow para que uma palavra-passe possa ser verificada em nome de um processo que não deve ler /etc/shadow. Retire a capacidade de obter essa identidade e o helper não consegue concluir a verificação, pelo que o módulo devolve uma falha de autenticação simples.

A falha parece então, em todos os registos que o cliente consegue ver, um problema de credenciais. É essa a armadilha: o cliente relata o que o PAM lhe disse, e o PAM relata apenas que a pilha disse não. Executar o helper à mão como root também não prova nada, porque exercita um caminho de privilégios que o serviço nunca usa. Leia a unidade que o systemd carregou de facto e depois leia o registo do sistema relativo à tentativa feita. Essas duas vistas separam um problema de sandbox de um problema de palavra-passe errada.

Leia a unidade antes de ler o registo de palavras-passe

Uma unidade empacotada pode trazer um drop-in que não escreveu, e a configuração efetiva é o resultado da fusão. Imprima a unidade tal como o systemd a vê, juntamente com as definições de sandbox que decidem se o helper se pode elevar. A inspeção apenas de leitura é suficiente nesta fase.

systemctl cat [email protected]
systemctl show [email protected] -p User -p Group -p CapabilityBoundingSet -p AmbientCapabilities -p NoNewPrivileges
journalctl -u [email protected] -b

O primeiro comando mostra de onde vêm a unidade e os seus drop-ins, o que importa porque uma substituição acrescentada há meses dura mais do que a memória da razão pela qual existe. O segundo imprime os valores de sandbox dos quais dependem as duas secções seguintes.

Compare o que vê com um anfitrião funcional da mesma distribuição e versão. Uma diferença em User, CapabilityBoundingSet ou NoNewPrivileges é uma pista concreta; uma diferença em comentários de prosa não é. Anote os valores antes de alterar seja o que for, porque uma comparação posterior contra um alvo em movimento não prova nada. Se o serviço correr como uma conta sem privilégios com um conjunto delimitador vazio, o helper quase não tem com que trabalhar.

Transformação de credenciais, acesso a ficheiros e política são três limites

Comece pelo que acontece durante o exec. Um binário setuid ou um ficheiro com file capabilities desencadeia uma transformação de credenciais, pelo que a identidade resultante não é uma continuação do chamador. O conjunto delimitador limita o que esse binário pode adquirir, e NoNewPrivileges bloqueia por completo ganhos de setuid, setgid e file capabilities. Qualquer um desses três pode parar o helper sem afetar qualquer outra função do serviço.

De seguida, separe a evasão discricionária ampla do acesso de leitura estreito. CAP_DAC_OVERRIDE ignora verificações discricionárias em quase todo o lado, enquanto CAP_DAC_READ_SEARCH abrange leitura e travessia de diretórios com os seus próprios poderes adicionais. São ferramentas diferentes com raios de ação diferentes, e nenhuma delas é uma forma de escrever deixe o PAM ler o ficheiro shadow.

Por fim, pergunte se a política obrigatória permite a ação de todo. Uma capacidade Linux não se sobrepõe ao SELinux, e possuí-la não prova nada sobre uma regra de imposição de tipos. Trate uma recusa de acesso a ficheiros e uma recusa de capacidade como provas diferentes, porque nomeiam correções diferentes e muitas vezes proprietários diferentes. Leia todos os campos do registo em vez da simples palavra denied. Que executável praticou a ação, em que domínio corria, que tipo de alvo tocou, que classe de objeto estava envolvida e que permissão a política recusou - cada um destes aspetos estreita a resposta de forma diferente.

Retire a recusa do registo de auditoria

Num anfitrião em modo enforcing, a trilha de auditoria é o único lugar que regista uma recusa. Consulte os eventos recentes e leia-os em relação ao carimbo de data e hora do login falhado, não em relação à hora em que começou a investigar.

ausearch -m AVC,USER_AVC -ts recent

Um resultado vazio não é prova de inocência. Significa ou que a auditoria não está a recolher, ou que a sua janela perdeu a tentativa, e ambas as possibilidades têm de ser excluídas antes de descartar a política.

A orientação de resolução de problemas SELinux da Red Hat coloca as verificações de rótulo e de configuração antes da geração de regras de permissão, o que é também a ordem certa para este problema. Um binário helper com rótulo errado e uma lacuna na política produzem recusas semelhantes mas exigem reparações diferentes. Gerar uma regra de permissão para um erro de rotulagem esconde a falha e deixa a próxima atualização de pacote reintroduzi-la. Confirme o rótulo do helper instalado antes de escrever qualquer política.

Prove a alteração com um login aceite e um rejeitado

Altere apenas o limite que demonstrou e depois teste os dois resultados. Uma conta que deve autenticar-se tem de ter êxito, e uma conta com palavra-passe errada tem de continuar a falhar. Uma alteração que faz com que todas as tentativas tenham êxito removeu a autenticação em vez de a reparar.

Execute uma tentativa de ligação real e leia o journal imediatamente depois. A linha que prova a correção é a entrada pam_unix(openvpn:auth) dessa tentativa: deve indicar sucesso de autenticação, e nenhum registo AVC deve ter o mesmo segundo.

journalctl -u [email protected] -n 30 --no-pager
ss -tnp | grep openvpn

Um túnel funcional também precisa de uma reconexão, porque as alterações de sandbox quebram a segunda ligação com mais frequência do que a primeira. Verifique o socket estabelecido após a reconexão e confirme que a mesma unidade continua a servi-lo.

Artigos relacionados