O Security Enhanced Linux (SELinux) é uma camada adicional de segurança do sistema. Ele não utiliza as regras de firewall (iptables, firewalld…) e também não utiliza o sistema de acesso/permissão “UGOA” (user, group, others, all).
A proposta do SELinux é utilizar Controle de Acesso Obrigatório (Mandatory Access Control, MAC) que é baseado em objeto, restringindo o acesso de um usuário ou iniciador a esse objeto.
O SELinux se baseia em um conjunto de regras de segurança que determinam qual processo pode acessar quais arquivos, diretórios e portas. Esse controle é feito através de um rótulo que cada processo, porta ou arquivo recebe. Esse rótulo, dentro do SELinux é conhecido “context”.
Cada contexto tem uma política de acesso para determinar o que pode ser acessado e o que não pode ser acessado. Porém, o SElinux funciona de forma restritiva, ou seja, caso a regra não seja explícita, o acesso será negado.
Os rótulos do SELinux têm vários contextos: usuário, função, tipo e sensibilidade.
A política direcionada (SELINUXTYPE=targeted que está no arquivo de configuração do SELinux, demonstrada a seguir), que é a política padrão ativada. Ele se baseia no contexto “TIPO”. Eles são facilmente identificados, pois geralmente terminam com _t.
Contexto do arquivo SELinux:
unconfined_u:object_r:user_home_dir_t:s0 /home/bruno/
_u: User
_r: Role
_t: Type
s: Level
Abaixo, alguns contextos de tipo para arquivos e diretórios:
– /home é user_home_dir_t;
– /var/www/html é httpd_sys_content_t;
– /tmp e /var/tmp é tmp_t.
Também há contextos para portas de um servidor web, por exemplo, que é o http_port_t.
Isso tudo impede que serviços que foram comprometidos não tenha acessos a outras áreas do sistemas operacional.
Um bom exemplo é o caso do Apache. Caso comprometido, o usuário e grupo apache têm acesso ao /tmp. Com as regras restritivas do SELinux, o acesso do apache só sera do diretório /var/www/html
Alguns comandos utilizam a opção “-Z” para exibir os contextos do SELinux.
Exemplos:
# ps uaZ
# ls -Z
ENTENDENDO E ALTERANDO OS ESTADOS DO SELINUX
Para fins didáticos, vamos separar o processo do SELinux em algumas partes.
A primeira, mais básica: Ativado e Desativado.
Ativado: Ele inicia junto ao sistema operacional;
Desativado: Ele NÃO inicia junto ao sistema operacional.
Para fazer isso na inicialização, pode passar um parâmetro no Kernel informando seus estados.
Para Desativar, basta passar o parâmetro selinux=0
Para Ativar, basta passar o parâmetro selinux=1
Mais a frente, demonstro como fazer no arquivo de configuração e de forma definitiva.
Quando o SELinux está Ativo, ele tem dois estados de funcionamento: Imposição (enforcing) e Permissivo (permissive)
Imposição: o SELinux está ativo e impõe que as regras de controle de acesso sejam utilizado no Sistema Operacional.
Permissivo: o SELinux está ativo mas apenas registra quais regras de controle de acesso foram violadas sem impedir qualquer tipo de acesso.
A vantagem da utilização do modo Permissivo é o fato de não alterar o acesso ao sistema e poder utilizar para estudos, testes ou correções de problemas.
Quando o SELinux está desativado, nem mesmo o registro dos acessos é feito.
Para fazer uma verificação manual do SELinux e assim saber em qual modo ele está, pode verificar manualmente ou através do seu arquivo de configuração
getenforce = Verifica o estado atual do SELinux.
setenforce = Aplica um novo estado para o SELinux
Para o modo Imposição (Enforcing):
“setenforce 1” ou “setenforce Enforcing“
Para o modo Permissivo (Permissive):
“setenforce 0” ou “setenforce Permissive“
ARQUIVO DE CONFIGURAÇÃO DO SELINUX
O arquivo de configuração do SELinux fica em “/etc/selinux/config“. Nele é possível modificar de forma definitiva o comportamento do SELinux ao iniciar o sistema;
# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing – SELinux security policy is enforced.
# permissive – SELinux prints warnings instead of enforcing.
# disabled – No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
# targeted – Targeted processes are protected,
# minimum – Modification of targeted policy. Only selected processes
# are protected.
# mls – Multi Level Security protection.
SELINUXTYPE=targeted
Basta utilizar o nome do estado do SELinux no parâmetro de mesmo nome.
SELINUX=enforcing
SELINUX=permissive
SELINUX=disabled
Ao finalizar, basta salvar o arquivo e reiniciar o sistema.
Quando o sistema é reiniciado, os parâmetros do Kernel são lidos. Assim como fizemos manualmente informando o estado Ativado ou Desativado, o arquivo de configuração irá informar se o SELinux está ativado selinux=0 ou 1 e qual o seu estado enforcing=0 ou 1
HERANÇAS DOS CONTEXTOS DO SELINUX
Como dito anteriormente, todos os processos e arquivos são rotulados. Novos arquivos herdam o contexto do diretório pai.
Porém, essa herança pode ser prejudicada de duas formas:
1 – Se um arquivo for criado em um diretório e movido para outro, o contexto será do diretório onde foi criado.
Exemplo:
# echo “Servidor Apache” >> /tmp/index.html
# ls -Z /tmp/index.html
# mv /tmp/index.html /var/www/html
# ls -Z /var/www/html/index.html
Observe que o contexto continuará como do diretório /tmp
unconfined_u:object_r:user_tmp_t:s0 /var/www/html/index.html
2 – A outra forma é copiando o arquivo e mantendo seus atributos (cp -a), pois o contexto é preservado.
# echo “Servidor Apache” >> /tmp/index.html
# ls -Z /tmp/index.html
# cp -a /tmp/index.html /var/www/html
# ls -Z /var/www/html/index.html
ALTERAÇÃO DOS CONTEXTOS DO SELINUX
Para alterar os contextos do SELinux, são necessário conhecer 3 comandos:
– semanage
– restorecon
– chcon
O “semanage” serve para fazer a declaração de qual será o rótulo padrão, porém ele tem que vir acompanhado do argumento fcontext.
O “restorecon” faz com que o contexto padrão seja aplicado aos diretórios e arquivos.
Já o “chcon” faz altera o contexto, porém não fica de forma permanente como o “semanage fcontext“. Ele é ideal para a realização de testes por não ficar permanente e pode ser facilmente removido com a execução do “restorecon“
Exemplo:
# mkdir /testeSeLinux
# ls -dZ /testeSeLinux
unconfined_u:object_r:default_t:s0 /testeSeLinux/
# chcon -t ssh_exec_t /testeSeLinux
# ls -dZ /home/bruno/testeSeLinux
unconfined_u:object_r:ssh_exec_t:s0 /testeSeLinux/
# restorecon -v /testeSeLinux
Relabeled /testeSeLinux from unconfined_u:object_r:ssh_exec_t:s0 to unconfined_u:object_r:default_t:s0
# ls -dZ /home/bruno/testeSeLinux
unconfined_u:object_r:default_t:s0 /testeSeLinux/
No exemplo acima:
– Criamos um diretório /testeSeLinux
– Mudamos o contexto, não definitivamente, de default_t para ssh_exec_t
– Restauramos o contexto do diretório /testeSeLinux para o padrão (default_t)
DEFINIÇÃO DAS REGRAS DE CONTEXTO PADRÃO DO SELINUX
Utilizando o “semanage fcontext“, podemos definir um novo contexto padrão para diretórios e arquivos.
O “restorecon” utiliza os contextos definidos pelo “semanage” para restaurar o contexto padrão.
A utilização do “semanage fcontext” pode ser para adicionar, deletar ou listar dos tipos de contexto:
-a (–all): Adiciona um registro
-d (–delete): Apaga um registro
-l (–list): Lista os registros
Para a utilização desses comandos, será necessário verificar se os pacotes policycoreutils e policycoreutils-python-utils estão instaladas em seu Sistema Operacional. Também é necessário o entendimento da seguinte expressão regular: (/.*)? que significa “opcionalmente, corresponder uma / seguida por qualquer número de caracteres” e na prática ele lê o diretório em questão e seus arquivos recursivamente.
A utilização segue a seguinte lógica:
# semanage fcontext -a -t contexto ‘/diretório(/.*)?’
A opção -a é utilizada para adicionar um contexto; A opção -t é o tipo do contexto.
O argumento é o diretório que será aplicado o contexto junto com a expressão regular no final, dentro de aspas simples.
Exemplo:
# mkdir /MeuSite
# echo “Teste do Meu Site” >> /MeuSite/index.html
# ls -Zd /MeuSite
# ls -Z /MeuSite
# semanage fcontext -a -t httpd_sys_content_t ‘/MeuSite(/.*)?’
# restorecon -RFvv /MeuSite
# ls -Zd /MeuSite
# ls -Z /MeuSite
AJUSTE DO SELINUX COM BOOLEANOS
Os booleanos do SELinux são opções que alteram o comportamento da política do SELinux, regras que podem ser habilitadas ou desabilitadas para fazer ajustes seletivos.
Instale o pacote selinux-policy-doc e com o comando “man -k _selinux” poderá ver todos os manuais disponíveis com todas as regras que utilizam booleanos.
Para fazer esses ajustes, utilizaremos os seguintes comandos:
– getsebool
– setsebool
– semanage boolean (Esse será utilizado apenas para consulta)
O comando “getsebool” lista os booleanos e seus estados. Pode listar todos de uma única vez (-a) ou um específico
# getsebool -a
# getsebool httpd_enable_homedirs
O comando “setsebool” modifica os valores dos booleanos
# setsebool httpd_enable_homedirs on
# semanage boolean -l | grep httpd_enable_homedirs
httpd_enable_homedirs (on , off) Allow httpd to enable homedirs
Nesse ponto você observará que existe entre parênteses as palavras on e off. No primeiro campo, indica o estado atual do valor daquele booleano e o segundo campo indica se aquele valor será persistente ao reiniciar o sistema. No exemplo acima, a opção httpd_enable_homedirs está ativada no momento, porém se a máquina for reiniciada esse estado voltará para desativado.
Para tornar esse valor persistente, vamos utilizar a opção -P.
# setsebool -P httpd_enable_homedirs on
# semanage boolean -l | grep httpd_enable_homedirs
httpd_enable_homedirs (on , on) Allow httpd to enable homedirs
Nesse momento, a opção httpd_enable_homedirs está ativada e caso seja necessário reiniciar o host, a opção permanecerá ativa.
Caso queira listar todos os booleanos que estão com o valor diferente do padrão, basta executar:
# semanage boolean -l -C
ENTENDENDO OS PROBLEMAS DO SELINUX
Todas as ações tomadas pelo SELinux são gravadas em log, portanto podemos utilizar essas informações para verificar se há algum serviço que o SELinux está impedindo de ser executado. Como vimos anteriormente, o “restorecon” server para restaurar o contexto padrão de um diretório. Ele pode resolver em muitos casos, porém é sempre importante entender como o SELinux funciona e suas mensagens para assim resolver o problema mais rapidamente.
Você precisa instalar o pacote setroubleshoot-server para que as mensagens do arquivo “/var/log/audit/audit.log” envie um resumo da informação que o SELinux gerar para o arquivo “/var/log/messages“. Caso sua distribuição não tenha o arquivo messages, instale o pacote rsyslog e inicie o serviço.
Exemplo:
Vamos simular um erro para que assim possa ser gerado o alerta no sistema de auditoria do linux e enviado para o arquivo de mensagens.
Você irá precisar instalar o apache para o exemplo a seguir:
# systemctl start httpd
# echo “Meu Site” >> /root/meusite.html
# mv /root/meusite.html /var/www/html
# curl http://localhost/meusite.html
Nesse momento você verá a seguinte mensagem do Apache:
<!DOCTYPE HTML PUBLIC “-//IETF//DTD HTML 2.0//EN”>
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don’t have permission to access /meusite.html
on this server.<br />
</p>
</body></html>
Isso gerou um alerta que está nos logs que comentamos anteriormente:
# tail /var/log/audit/audit.log
…
type=AVC msg=audit(1598297683.712:239): avc: denied { getattr } for pid=5356 comm=”httpd” path=”/var/www/html/meusite.html” dev=”dm-0″ ino=8409719 scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file permissive=0
…
# tail /var/log/messages
…
localhost setroubleshoot[1913]: SELinux is preventing httpd from getattr access on the file /var/www/html/meusite.html. For complete SELinux messages run: sealert -l 14fa81a0-f8be-40a1-82da-908440c823c8
…
Nos dois arquivos, é possível observar a negação do acesso ao arquivo “/var/www/html/meusite.html“
No arquivo messages, é possível ver a sugestão da utilização do comando “sealert” para ver informações adicionais
# sealert -l 14fa81a0-f8be-40a1-82da-908440c823c8
O “sealert” trará o mesmo conteúdo, mas de duas formas. Uma mais organizada e outra no modo “raw” que trás o mesmo conteúdo do “audit.log“
Utilizando a saída do “sealert“, é possível observar três campos importante para o nosso erro:
Contexto de origem system_u:system_r:httpd_t:s0
Contexto de destino unconfined_u:object_r:admin_home_t:s0
Objetos de destino /var/www/html/meusite.html [ file ]
no Raw messages:
scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 path=”/var/www/html/meusite.html”
O “Contexto de origem” ou “scontext” é o contexto que o selinux espera para o “Objetos de destino” ou “path“. Já o “Contexto de destino” ou “tcontext” mostra a informação que o SELinux encontrou no “Objetos de destino” ou “path“. No nosso caso, era esperado “httpd_t” e foi encontrado “admin_home_t“, pois o arquivo foi criado no “/root” (admin_home_t) e movido para “/var/www/” e como vimos anteriormente, isso gera um erro.
Vamos verificar como está o contexto de “/var/www/html“
# ls -Zd /var/www/html
system_u:object_r:httpd_sys_content_t:s0 /var/www/html
Agora vamos restaurar o contexto dos arquivos dentro do diretório “/var/www/html“
# restorecon -RFvv /var/www/html/
Relabeled /var/www/html/meusite.html from unconfined_u:object_r:admin_home_t:s0 to system_u:object_r:httpd_sys_content_t:s0
A saída do comando (por causa da opção -vv) mostra que o contexto do arquivo foi alterado de admin_home_t para httpd_sys_content_t. Com isso, o arquivo html deve estar disponível para acesso.
# curl http://localhost/meusite.html
Meu Site
Apesar de uma explicação básica sobre o SELinux, é possível entender sua importância, como trabalhar com ele e ainda tratar alguns erros.
O objetivo é tirar um pouco da ideia que o SELinux é muito complicado e que só serve para desabilitar após a instalação.
Referências:
https://www.redhat.com/pt-br/topics/linux/what-is-selinux
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/using_selinux/index