O Linux é seguro? A resposta é enfática: não. Ou mais flexivelmente: depende. Mas depende de quê? Depende de quem o administra. Um Linux mal configurado pode ser tão ou até mais vulnerável do que outro sistema qualquer. Nesse artigo apresentaremos as principais fontes de vulnerabilidade do Linux e algumas medidas para torná-lo mais seguro.
Introdução
- Assim como nas versões anteriores do UNIX, o GNU/Linux é otimizado para conveniência, não para segurança. Os sistemas geralmente são manipulados de maneira a oferecer facilidades ao administrador, em detrimento da segurança. Todo administrador de sistemas deve ter em mente que: Segurança = 1/ (1.000.000 x Conveniência).
- A segurança é quase que binária: ou você é um usuário sem poderes no sistema ou você é o root! E lembre-se que como root, você pode tudo. TUDO MESMO! Inclusive destruir todo seu sistema ou comprometer sua segurança por completo. Algumas características do sistema, tais como execução com “setuid” tendem a dar poderes de root para usuários quaisquer, de forma que qualquer deslize na utilização de tais facilidades pode comprometer o sistema por completo.
- O GNU/Linux é desenvolvido por uma grande comunidade de programadores, dos mais variáveis níveis de conhecimento, experiência e grau de atenção. Devido a essa grande variedade de desenvolvedores, até mesmo os mais bem-intencionados estão sujeitos a introduzir falhas de segurança no sistema. Por outro lado, o código é aberto e está disponível para todos, de modo que é muito mais fácil se descobrirem falhas de segurança do que em sistemas fechados. Esse é um dos grandes trunfos do GNU/Linux que o tornam geralmente mais seguros do que sistemas fechados.
No decorrer do artigo faremos uma introdução sobre os principais conceitos relacionados à segurança em sistemas GNU/Linux, apresentando soluções para torná-los cada vez menos vulneráveis. Já que é impossível termos um sistema 100% seguro, então vamos tentar aumentar o máximo esse nível de segurança. Nas seções seguintes abordaremos algumas das principais questões de segurança a serem consideradas no GNU/Linux, apresentando conceitualmente alguns aspectos aos quais devemos estar sempre atentos de forma a proteger nosso sistema.
Filtragem de pacotes
Filtragem por endereços de origem e destino
Qualquer pacote TCP/IP possui um endereço IP de origem e outro de destino associados. Ao longo do caminho percorrido pelos pacotes na rede, tais endereços permanecem intactos. A filtragem por endereços pode ser feita tanto pela origem quanto pelo destino (ou ambos), tendo como base o endereço de um host específico ou mesmo o endereço de uma rede inteira. A seguir, alguns exemplos de utilização desse tipo de filtragem:
- Controlar o acesso para algumas máquinas (endereços de origem e destino);
- Bloquear ou liberar determinados serviços somente para algumas máquinas ou redes (endereço de destino);
- Bloquear ou liberar o tráfego de pacotes provindos de determinada origem (endereço de origem);
- Evitar tentativas de “IP spoofing” (endereço de origem);
- Dificultar tentativas de ataque do tipo “Denial of Service”, filtrando endereços inválidos (endereço de origem).
Filtragem por portas de origem e destino
Cada serviço de rede de um sistema possui uma porta associada a ele, pela qual é provido o acesso ao serviço. Uma listagem completa das correlações entre números de portas e serviços pode ser vista em:
Dentre todos os serviços de rede existentes, alguns são famosos por apresentarem brechas que podem ser utilizadas por atacantes. Serviços como o ftp, tftp, finger, pop e outros, muitas vezes precisam estar presentes nas regras de filtragem de pacotes.
Filtragem por protocolo
É possível também definir regras de filtragem para bloquear ou permitir tráfego de pacotes de determinado protocolo: UDP, TCP, ICMP ou RPC. Na maioria das vezes, as regras de filtragem são definidas combinando-se os conceitos de filtragem por endereço, por porta e por protocolo, de modo que seja possível definir as regras mais específicas possíveis para se atender a determinada necessidade.
Implementações de filtros de pacotes
A filtragem de pacotes pode ser implementada de maneiras diferentes. É possível definir regras de filtragem dentro de um roteador, por exemplo. Tais regras em um roteador são chamadas de “access-list” (listas de acesso).
Uma segunda abordagem para filtragem de pacotes, é fazê-la utilizando um dispositivo que chamamos de “firewall”. O termo em inglês faz alusão à sua função de evitar o alastramento de dados nocivos dentro de uma rede, da mesma maneira que uma parede corta-fogo (firewall) evita o alastramento de incêndios em uma casa.
Firewalls podem ser implementados por software, por hardware ou por uma combinação de ambos. A implementação depende do tamanho da rede, da complexidade das regras permitidas e do grau de segurança desejado. Para redes de maior tráfego de dados, recomenda-se a utilização de hardware dedicado para firewall. Uma implementação por software bastante conhecida no mundo do software livre é o “iptables”.
Serviços desnecessários
Outra maneira é verificando portas do sistema que estão abertas. Para esse fim, podemos utilizar uma poderosa ferramenta para verificação de rede: o “nmap” (port-scanner):
# nmap -sS 127.0.0.1
A saída do “nmap” será algo do tipo:
Starting Nmap 4.11 ( http://www.insecure.org/nmap/ ) at 2007-04-21 22:38 BRT
Interesting ports on localhost.localdomain (127.0.0.1):
Not shown: 1670 closed ports
PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp 80/tcp open http 111/tcp open rpcbind 716/tcp open unknown 842/tcp open unknown 2049/tcp open nfs 3306/tcp open mysql
Nmap finished: 1 IP address (1 host up) scanned in 0.144 seconds
Através dessa saída, é possível verificar quais as portas estão abertas em nosso sistema e a partir disso, julgarmos o que é necessário continuar aberto e o que deve ser fechado ou filtrado.
Controle dos serviços de rede
Alguns serviços de rede oferecem a opção de serem executados como “daemons” ou através do “inetd”. É recomendável executar um serviço no modo “daemon” se este for um serviço solicitado freqüentemente (tais como servidores web, proxy, etc), ou através do “inetd”, caso contrário (tais como servidores de ftp, ssh, etc).
Serviços de rede que rodam como “daemons”, geralmente são iniciados no momento do boot (pelos scripts de inicialização presentes em /etc/init.d) e permanecem o tempo todo na memória aguardando que alguém se conecte a ele. Serviços executados como “daemons” aparecem no sistema como um processo qualquer e podem ser verificados facilmente utilizando-se o comando “ps”.
Serviços iniciados pelo “inetd” são carregados na memória somente no momento em que são solicitados. A configuração de quais serviços podem ser carregados pelo “inetd” e seus parâmetros é feita através do arquivo /etc/inetd.conf. O “inetd” lê as configurações deste arquivo e permanece na memória, aguardando a conexão dos clientes.
inetd.conf
O arquivo inetd.conf possui uma sintaxe simples, em que cada linha descreve um serviço que se deseja oferecer. A sintaxe é a seguinte:
<nome_serviço> <tipo_soquete> <proto> <opção> <usuário> <caminho_servidor> <argumentos>
Em que:
- “serviço” é o serviço que se deseja oferecer
- “tipo_soquete” é o tipo do soquete que este item utilizará (geralmente stream para serviços baseados em TCP ou dgram para serviços baseados em UDP)
- “protocolo” é o tipo de protocolo de transporte utilizado (geralmente TCP ou UDP)
- “opção” indica se o serviço de rede libera o soquete após ele ser iniciado (nowait) ou se o “inetd” deve aguardar e assumir que qualquer servidor já em execução pegará a nova requisição de conexão (wait).
- “usuário” define o dono do “daemon” de rede
- “caminho_servidor” é o caminho para o programa servidor atual que será executado.
- “argumentos” são argumentos da linha de comando que se deseje passar para o daemon servidor quando for iniciado.
Patches de segurança e “Bug Report”
Devido às frequentes descobertas de falhas de segurança em versões de programas do Linux, foram criadas várias comunidades para a disseminação de informações sobre falhas de segurança e correção de vulnerabilidades. A seguir, alguns endereços de sites de comunidades dedicadas à propagação de tais informações:
- http://www.securityfocus.com
- http://www.linuxsecurity.com.br
- http://www.cert.org
- http://www.infosecwriters.com
O que esses sites fazem é divulgar os bugs reportados pela comunidade ao redor do mundo (geralmente em listas de discussão de desenvolvedores), além de publicar uma lista de “exploits” que podem ser utilizados para explorar determinadas falha de segurança e também as atualizações de versão de programas. Por “exploit”, entende-se um programa que explora determinada falha de segurança com a finalidade de prover acesso ao sistema atacado.
Backup
Cabe ao administrador definir as políticas de backup do seu sistema de rede. Isso dependerá do tamanho da rede, da quantidade de dados que necessitam backup, da frequência com que o backup deverá ser realizado e dos recursos que se têm disponíveis.
Senhas
Isso ocorre porque esse algoritmos inversos possuem complexidade computacional exponencial e, para reverter o processo de encriptação, seria necessários milhões de anos executando um algoritmo dessa natureza, mesmo contanto com as máquinas mais modernas da atualidade.
O que programas de “força bruta” fazem é gerar senhas, criptografá-las usando o mesmo algoritmo de criptografia utilizado nos sistemas Linux (que são algoritmos computacionalmente simples) e comparar tais senhas criptografadas com uma senha criptografada existente no sistema.
Mas o grande trunfo de tais programas é o fato de que as senhas geradas por ele não são aleatórias. São senhas baseadas em dicionários (ou “wordlists”) pré-determinados, ou seja, dicionários que contém as expressões que são mais usadas em senhas, tais como datas, nomes, etc.
O mais famoso desses programas de força bruta para GNU/Linux é o John the Ripper, que pode ser encontrado em:
Vários dicionários para diversos idiomas e para diversos temas diferentes podem ser encontrados na internet. Uma dica é o site:
Pelas razões expostas acima, é preciso ter extremo cuidado com os arquivos que armazenam as senhas do sistema: /etc/passwd e /etc/shadow. É necessário sempre verificar que toda conta tenha uma senha associada, para evitar que usuários tenham acesso ao sistema sem necessidade de senha.
Existem várias ferramentas para checar a existência de problemas nos arquivos de senha, mas aqui está uma forma extremamente simples de verificar, por exemplo, se existe algum usuário com senha nula:
# perl -F: -ane 'print if not $F[1];' /etc/shadow</b>
Permissões
É importante que o administrador do sistema tenha pleno conhecimento do sistema de permissões do GNU/Linux, bem como as opções de permissões especiais: “setuid”, “setgid” e “stick bit”. Outra ferramenta que aumenta o grau de segurança do sistema é o “sudo”, que permite a um usuário em particular executar vários comandos como super usuário sem que possua a senha do root, com a vantagem de que tudo que será feito, será gravado em arquivos de log.
Conclusão
Um abraço a todos!
Sílvio Cruz