Uma das razões para o enorme sucesso do sistema operacional Linux em dispositivos embarcados, móveis e servidores é o elevado nível de segurança do núcleo, dos serviços complementares e das aplicações. Mas se a arquitetura do núcleo Linux, não encontraremos um quadrado responsável pela segurança, propriamente dita. Onde, então, está a subsistema de segurança do Linux e do que ela é composta?
Histórico dos Módulos de Segurança do Linux e SELinux
O Security Enhanced Linux é um conjunto de regras e mecanismos de acesso, baseado em modelos de acesso mandatório e por papéis, para proteger sistemas Linux contra ameaças potenciais e corrigir as deficiências do Controle de Acesso Discricionário (DAC) — o sistema de segurança tradicional do Unix. O projeto nasceu nas entranhas da Agência Nacional de Segurança dos EUA, sendo desenvolvido, principalmente, por contratados da Secure Computing Corporation e MITRE, além de vários laboratórios de pesquisa.

Módulos de Segurança do Linux
Linus Torvalds fez várias observações sobre os novos desenvolvimentos da NSA, para que pudessem ser incluídos no ramo principal do núcleo Linux. Ele descreveu um ambiente geral, com um conjunto de interceptadores para gerenciar operações com objetos e um conjunto de campos de proteção nas estruturas de dados do núcleo para armazenar atributos correspondentes. Esse ambiente pode ser usado por módulos de núcleo carregáveis para implementar qualquer modelo de segurança desejado. O LSM foi completamente integrado ao núcleo Linux v2.6 em 2003.
O framework LSM inclui campos de proteção nas estruturas de dados e chamadas de funções de interceptação em pontos críticos do código do núcleo para gerenciá-los e executar o controle de acesso. Ele também adiciona funções para registrar módulos de segurança. A interface /sys/kernel/security/lsm contém uma lista de módulos ativos no sistema. Os hooks do LSM são armazenados em listas, que são invocadas na ordem especificada em CONFIG_LSM. A documentação detalhada sobre os hooks está incluída no arquivo de cabeçalho include/linux/lsm_hooks.h.
O subsistema LSM permitiu a conclusão da integração do SELinux na mesma versão estável do núcleo Linux v2.6. Praticamente imediatamente, o SELinux se tornou o padrão de fato para ambientes Linux protegidos e foi incluído nas distribuições mais populares: RedHat Enterprise Linux, Fedora, Debian, Ubuntu.
Glossário SELinux
- Identidade — O usuário SELinux não é o mesmo que o id do usuário Unix/Linux tradicional; eles podem coexistir no mesmo sistema, mas são completamente diferentes em essência. Cada conta padrão do Linux pode corresponder a uma ou mais no SELinux. A identidade SELinux é uma parte integrante do contexto de segurança geral, que define a quais domínios se pode entrar e a quais não se pode.
- Domínios — No SELinux, um domínio é o contexto de execução de um sujeito, ou seja, um processo. O domínio define diretamente o acesso que o processo possui. Um domínio é essencialmente uma lista do que os processos podem fazer ou quais ações um processo pode realizar com diferentes tipos. Alguns exemplos de domínios: sysadm_t para administração de sistema, e user_t, que é o domínio normal e não privilegiado do usuário. O sistema de inicialização init é executado no domínio init_t, enquanto o processo named é executado no domínio named_t.
- Funções — O que serve como intermediário entre domínios e usuários do SELinux. As funções definem a quais domínios um usuário pode pertencer e a que tipos de objetos ele poderá ter acesso. Esse mecanismo de controle de acesso previne a ameaça de ataques de elevação de privilégios. As funções estão inseridas no modelo de segurança Role Based Access Control (RBAC), usado no SELinux.
- Tipos — Atributo da lista Type Enforcement, que é atribuído a um objeto e define quem terá acesso a ele. É semelhante à definição de um domínio, exceto que o domínio se aplica ao processo, enquanto o tipo se aplica a objetos como diretórios, arquivos, sockets, etc.
- Sujeitos e objetos — Processos são sujeitos e são executados em um contexto específico, ou domínio de segurança. Os recursos do sistema operacional: arquivos, diretórios, sockets e outros, são objetos que recebem um tipo específico, ou seja, um nível de confidencialidade.
- Políticas SELinux — Para proteger o sistema, SELinux utiliza várias políticas. A política SELinux define o acesso dos usuários às funções, das funções aos domínios, e dos domínios aos tipos. Primeiro, o usuário é autorizado a obter uma função, em seguida, a função é autorizada a acessar os domínios. Finalmente, um domínio pode ter acesso apenas a alguns tipos de objetos.
LSM e arquitetura SELinux
Embora o nome LSM não se refira a módulos carregáveis do Linux, assim como o SELinux, ele está diretamente integrado ao núcleo. Qualquer alteração no código-fonte do LSM exige uma nova compilação do núcleo. A opção correspondente deve estar ativada nas configurações do núcleo, caso contrário, o código do LSM não será ativado após a inicialização. Mesmo assim, ainda pode ser ativado através da opção do carregador de inicialização do sistema operacional.

Pilha de verificações do LSM
O LSM está equipado com hooks nas funções principais do núcleo que podem ser relevantes para as verificações. Uma característica fundamental do LSM é que ele é estruturado como uma pilha. Assim, as verificações padrão ainda são realizadas, e cada camada do LSM apenas adiciona elementos adicionais de controle e supervisão. Isso significa que uma proibição não pode ser revertida. Isso é demonstrado na figura; se o resultado das verificações DAC rotineiras for uma recusa, então o processo nem mesmo chegará aos hooks do LSM.
O SELinux adotou a arquitetura de segurança Flask do sistema operacional Fluke, particularmente o princípio do menor privilégio. A essência deste conceito, conforme indicado pelo próprio nome, é fornecer ao usuário ou processo apenas os direitos necessários para realizar as ações pretendidas. Este princípio é implementado por meio da tipificação de acesso forçada, assim, o controle de acesso no SELinux é baseado no modelo domínio => tipo.
Graças à tipificação de acesso forçada, o SELinux possui capacidades de controle de acesso muito mais significativas do que o modelo DAC tradicional, usado em sistemas operacionais Unix/Linux. Por exemplo, é possível restringir o número da porta de rede que será utilizada pelo servidor FTP, permitir gravação e modificações de arquivos em uma determinada pasta, mas não a sua exclusão.
Os componentes principais do SELinux são:
- Servidor de Aplicação de Política — O principal mecanismo de organização do controle de acesso.
- Banco de dados de políticas de segurança do sistema.
- Interação com o interceptador de eventos do LSM.
- Selinuxfs — Sistema de arquivos pseudo, semelhante ao /proc, montado em /sys/fs/selinux. É preenchido dinamicamente pelo núcleo do Linux durante a execução e contém arquivos que contêm informações sobre o status do SELinux.
- Cache de Vetores de Acesso — Mecanismo auxiliar para aumento de desempenho.

Funcionamento do SELinux
Tudo isso funciona da seguinte maneira.
- Um determinado sujeito, em termos de SELinux, realiza uma ação permitida sobre um objeto após a verificação DAC, como mostrado na imagem acima. Esta solicitação para a realização da operação é enviada para o interceptador de eventos LSM.
- A partir daí, a solicitação, junto com o contexto de segurança do sujeito e do objeto, é enviada ao módulo SELinux Abstraction and Hook Logic, responsável pela interação com o LSM.
- A instância que toma a decisão sobre o acesso do sujeito ao objeto é o Policy Enforcement Server, e para ele, os dados são fornecidos pelo SELinux AnHL.
- Para tomar uma decisão de acesso ou negação, o Policy Enforcement Server consulta o subsistema de cache das regras mais utilizadas, o Access Vector Cache (AVC).
- Se a decisão para a regra correspondente não for encontrada no cache, a solicitação é enviada para o banco de dados de políticas de segurança.
- O resultado da pesquisa no banco de dados e no AVC é retornado ao Policy Enforcement Server.
- Se a política encontrada estiver de acordo com a ação solicitada, a operação é autorizada. Caso contrário, a operação é negada.
Gerenciamento das configurações do SELinux
O SELinux opera em um dos três modos:
- Enforcing — Aplicação rigorosa das políticas de segurança.
- Permissive — Violações de restrições são permitidas, com a anotação apropriada no log.
- Disabled — As políticas de segurança não estão em vigor.
Para verificar em qual modo o SELinux está, use o seguinte comando.
[admin@server ~]$ getenforce
PermissivePara mudar o modo antes da reinicialização, por exemplo, definindo como enforcing, ou 1. O parâmetro permissive corresponde ao código numérico 0.
[admin@server ~]$ setenfoce enforcing
[admin@server ~]$ setenfoce 1 #o mesmo
O modo também pode ser alterado editando o arquivo:
[admin@server ~]$ 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=impositivo
# SELINUXTYPE= can take one of three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targete
A diferença em relação ao setenfoce é que, ao iniciar o sistema operacional, o modo do SELinux será definido de acordo com o valor do parâmetro SELINUX do arquivo de configuração. Além disso, as alterações entre enforcing disabled só entram em vigor ao editar o arquivo /etc/selinux/config e após a reinicialização.
Verifique um breve relatório de status:
[admin@server ~]$ sestatus Status do SELinux: habilitado
Montagem do SELinuxfs: /sys/fs/selinux
Diretório raiz do SELinux: /etc/selinux
Nome da política carregada: direcionada
Modo atual: permissivo
Modo do arquivo de configuração: reforçado
Status da política MLS: habilitado
Status da política deny_unknown: permitido
Versão máxima da política do kernel: 31
Para visualizar os atributos do SELinux, algumas utilidades padrão usam o parâmetro -Z.
[admin@server ~]$ ls -lZ /var/log/httpd/
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200920
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20200927
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201004
-rw-r--r--. root root system_u:object_r:httpd_log_t:s0 access_log-20201011
[admin@server ~]$ ps -u apache -Z
LABEL PID TTY TIME CMD
system_u:system_r:httpd_t:s0 2914 ? 00:00:04 httpd
system_u:system_r:httpd_t:s0 2915 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 2916 ? 00:00:00 httpd
system_u:system_r:httpd_t:s0 2917 ? 00:00:00 httpd
...
system_u:system_r:httpd_t:s0 2918 ? 00:00:00 httpdEm comparação com a saída normal do ls -l, aqui há alguns campos adicionais no seguinte formato:
:::
O último campo indica algo como um rótulo de confidencialidade e é composto por uma combinação de dois elementos:
- s0 — significância, também é anotada através de um intervalo lowlevel-highlevel
- c0, c1… c1023 — categoria.
Alteração da configuração de acessos
Use semodule para carregar módulos SELinux, adicioná-los e removê-los.
[admin@server ~]$ semodule -l |wc -l #lista de todos os módulos
408
[admin@server ~]$ semodule -e abrt #habilitar módulo
[admin@server ~]$ semodule -d accountsd #desabilitar módulo
[admin@server ~]$ semodule -r avahi #remover móduloO primeiro comando semanage login vincula um usuário SELinux a um usuário do sistema operacional, o segundo exibe a lista. Por fim, o último comando com a chave -r remove a vinculação entre os usuários SELinux e as contas do SO. A explicação da sintaxe dos valores MLS/MCS Range está na seção anterior.
[admin@server ~]$ semanage login -a -s user_u karol
[admin@server ~]$ semanage login -l Nome de Login Usuário SELinux Intervalo MLS/MCS Serviço
__default__ unconfined_u s0-s0:c0.c1023 *
root unconfined_u s0-s0:c0.c1023 *
system_u system_u s0-s0:c0.c1023 *
[admin@server ~]$ semanage login -d karol
Time semanage user é usado para gerenciar as vinculações entre usuários e funções do SELinux.
[admin@server ~]$ semanage user -l
Labeling MLS/ MLS/
Usuário SELinux Prefix Nível MCS Intervalo MCS Funções SELinux
guest_u user s0 s0 guest_r
staff_u staff s0 s0-s0:c0.c1023 staff_r sysadm_r
...
user_u user s0 s0 user_r
xguest_u user s0 s0 xguest_r
[admin@server ~]$ semanage user -a -R 'staff_r user_r'
[admin@server ~]$ semanage user -d test_uParâmetros do comando:
- -a adicionar um registro de vinculação de função do usuário;
- -l listar a vinculação de usuários e funções;
- -d remover um registro de vinculação de função do usuário;
- -R listar as funções anexadas ao usuário;
Arquivos, portas e valores booleanos
Cada módulo SELinux fornece um conjunto de regras de marcação de arquivos, mas também é possível adicionar regras personalizadas, se necessário. Por exemplo, queremos dar ao servidor web permissão para acessar a pasta /srv/www.
[admin@server ~]$ semanage fcontext -a -t httpd_sys_content_t "/srv/www(/.*)?
[admin@server ~]$ restorecon -R /srv/www/O primeiro comando registra novas regras de marcação, enquanto o segundo redefine, ou melhor, define, os tipos de arquivos de acordo com as regras atuais.
Da mesma forma, as portas TCP/UDP são marcadas de forma que apenas os serviços correspondentes possam escutá-las. Por exemplo, para que o servidor web possa escutar a porta 8080, precisamos executar o comando.
[admin@server ~]$ semanage port -m -t http_port_t -p tcp 8080Um número significativo de módulos SELinux possuem parâmetros que podem assumir valores booleanos. A lista completa desses parâmetros pode ser vista com o comando getsebool -a. Os valores booleanos podem ser alterados com setsebool.
[admin@server ~]$ getsebool httpd_enable_cgi
httpd_enable_cgi --> on
[admin@server ~]$ setsebool -P httpd_enable_cgi off
[admin@server ~]$ getsebool httpd_enable_cgi
httpd_enable_homedirs --> off
Prática, acessar a interface do Pgadmin-web
Vamos considerar um exemplo prático, instalamos o pgadmin4-web no RHEL 7.6 para gerenciamento do banco de dados PostgreSQL. Passamos por um pequeno com a configuração do pg_hba.conf, postgresql.conf e config_local.py, definimos permissões nas pastas e instalamos os módulos Python ausentes via pip. Tudo pronto, iniciamos e obtemos 500 Internal Server error.

Começamos pelos suspeitos típicos, verificamos /var/log/httpd/error_log. Lá há algumas entradas interessantes.
[timestamp] [core:notice] [pid 23689] Política SELinux ativada; httpd rodando como contexto system_u:system_r:httpd_t:s0
...
[timestamp] [wsgi:error] [pid 23690] [Errno 13] Permissão negada: '\/var\/lib\/pgadmin'
[timestamp] [wsgi:error] [pid 23690]
[timestamp] [wsgi:error] [pid 23690] DICA : Você pode precisar definir manualmente as permissões em
[timestamp] [wsgi:error] [pid 23690] \/var\/lib\/pgadmin para permitir que o apache escreva nele.
Neste ponto, a maioria dos administradores Linux sentirá uma intensa tentação de executar setenforce 0 e dar o assunto por encerrado. Para ser honesto, da primeira vez eu fiz exatamente isso. Isso, claro, também é uma solução, mas não é a melhor.
Apesar da complexidade das construções, o SELinux pode ser amigável ao usuário. Basta instalar o pacote setroubleshoot e verificar o log do sistema.
[admin@server ~]$ yum install setroubleshoot
[admin@server ~]$ journalctl -b -0
[admin@server ~]$ service restart auditd
Note que o serviço auditd deve ser reiniciado exatamente assim, e não com systemctl, apesar da presença do systemd no sistema operacional. No log do sistema será indicado não apenas o fato de bloqueio, mas também a razão e a maneira de contornar a proibição.

Executamos esses comandos:
[admin@server ~]$ setsebool -P httpd_can_network_connect 1
[admin@server ~]$ setsebool -P httpd_can_network_connect_db 1
Verificamos o acesso à página da web pgadmin4-web, está tudo funcionando.
Fonte: habr.com
