Escolar Documentos
Profissional Documentos
Cultura Documentos
Defesa em Servidores Linux
Defesa em Servidores Linux
Novatec
All rights reserved. This translation is published under license with the original publisher John
Wiley & Sons, Inc. Copyright © 2016 by John Wiley & Sons, Inc., Indianapolis, Indiana.
Todos os direitos reservados. Tradução autorizada da edição em inglês intitulada Linux® Server
Security: Hack and Defend, publicada pela John Wiley & Sons, Inc. Copyright © 2016 por John
Wiley & Sons, Inc., Indianapolis, Indiana.
Nenhuma parte deste livro pode ser reproduzida, armazenada ou transmitida em qualquer formato
ou por qualquer meio, eletrônico, físico e etc., sem a autorização por escrito do titular original do
copyright, John Wiley & Sons, Inc. http://www.wiley.com/go/permissions
Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998. É proibida a reprodução
desta obra, mesmo parcial, por qualquer processo, sem prévia autorização, por escrito, do autor e da
Editora.
Editor: Rubens Prates
Tradução: Henrique Cesar Ulbrich
Revisão gramatical: Priscila A. Yoshimatsu
Editoração eletrônica: Carolina Kuwabata
ISBN: 978-85-7522-661-2
Histórico de edições impressas:
Janeiro/2017 Primeira edição
Novatec Editora Ltda.
Rua Luís Antônio dos Santos 110
02460-000 – São Paulo, SP – Brasil
Tel.: +55 11 2959-6529
E-mail: novatec@novatec.com.br
Site: www.novatec.com.br
Twitter: twitter.com/novateceditora
Facebook: facebook.com/novatec
LinkedIn: linkedin.com/in/novatec
Eu era terrível na escola. Reprovei tantas vezes em matemática que não
consigo nem contar.
— Stewart Francis
Sumário
Sobre o autor
Sobre o editor técnico
Como este livro é organizado
Quem deve ler este livro
Resumo
Capítulo 1 ■ Manto de invisibilidade
Contexto
Sondagem de portas
Como confundir um scanner de porta
Instalação do knockd
Pacotes
Alteração dos ajustes default
Alteração dos locais do sistema de arquivos
Algumas opções de configuração
Inicialização do serviço
Alteração da interface de rede default
Tipos de pacotes e temporizações
Teste da instalação
Clientes de port knocking
Como tornar o servidor invisível
Teste do iptables
Gravando as regras do iptables
Outras considerações
Cliente para smartphone
Pesquisa de problemas
Considerações de segurança
Sequências efêmeras
Resumo
Capítulo 2 ■ Coloque impressão digital em seus arquivos
Integridade do sistema de arquivos
Sistema de arquivos como um todo
Rootkits
Configuração
Falso-positivos
Bem projetado
Resumo
Capítulo 3 ■ Netcat no século 21
História
Pacotes de instalação
Para começar
Transferência de arquivos
Exemplo de bate-papo
Encadeamento de comandos
Comunicações seguras
Executáveis
Listas de controle de acesso
Opções diversas
Resumo
Capítulo 4 ■ Negação de serviço
Infraestrutura NTP
Ataques reflexivos NTP
Relatórios de ataques
Prevenção de reflexões SNMP
Resolvedores DNS
Cumplicidade
Uma nação de joelhos
Mapeamento de ataques
Resumo
Capítulo 5 ■ Nping
Funcionalidade
TCP
Intérprete
UDP
ICMP
ARP
Opções de payload
Modo Eco
Outras opções Nping
Resumo
Capítulo 6 ■ Análise de logs
Equívocos no uso de ICMP
tcpdump
Iptables
Regras multipartes
Registro completo para análise forense
Hardening
Resumo
Capítulo 7 ■ O prodigioso NSE do Nmap
Escaneamento de portas básico
Motor de script do Nmap
Modelos de temporização (timing templates)
Categorização de scripts
Fatores de contribuição
Falhas de segurança
Testes de autenticação
Descoberta
Atualização de scripts
Tipos de script
Expressões regulares
Interfaces gráficas de usuário
Zenmap
Resumo
Capítulo 8 ■ Detecção de malware
Para começar
Frequência de atualização das definições
Registro de hashes de malware
Ameaças prevalentes
Funcionalidades LMD
Monitoração de sistemas de arquivos
Instalação
Modos de monitoração
Configuração
Exclusões
Execução a partir da CLI
Relatórios
Quarentena e limpeza
Atualização do LMD
Execução e parada de varreduras
Tarefa cron
Relatórios de malware
Integração com Apache
Resumo
Capítulo 9 ■ Quebra de senhas com Hashcat
História
Compreensão das senhas
Keyspace
Hashes
Uso da Hashcat
Capacidades da Hashcat
Instalação
Identificação por hash
Escolha do modo de ataque
Download de uma wordlist
Tabelas rainbow
Execução da Hashcat
oclHashcat
Hashcat-utils
Resumo
Capítulo 10 ■ Ataques de injeção de SQL
História
SQLi básica
Mitigação de SQLi em PHP
Exploração de falhas SQL
Lançamento de um ataque
Testando a SQLi de forma legal
Resumo
Sobre o autor
Chris Binnie é um consultor técnico que trabalhou com sistemas Linux online
por quase duas décadas. Durante sua carreira, ele instalou muitos
servidores, tanto na nuvem quanto em máquinas físicas, e em bancos e
órgãos governamentais. Além disso, construiu uma rede de sistemas
autônomos em 2005 e um serviço de vídeo em HD para 77 países sobre
uma plataforma de streaming de mídia que ele concebeu e construiu.
Escreveu para a Linux Magazine e para a ADMIN Magazine por muitos
anos. Fora do trabalho, Chris gosta de realizar atividades ao ar livre, assistir
ao time de futebol Liverpool FC e exaltar as virtudes da infalível navalha de
Occam.
Resumo
A expectativa é que, pelo aumento da compreensão das ferramentas e da
forma de pensar de um hacker e conhecendo os últimos recursos de
segurança, você não fique sujeito a um fato comum hoje em dia: o da
pessoa que não tem mais controle sobre os seus próprios sistemas ou redes,
enquanto outra pessoa lá fora tem.
CAPÍTULO 1
Manto de invisibilidade
Contexto
Pela simples camuflagem da existência de um servidor na internet,
podemos no mínimo fazer uma máquina rodar em privado e, no pior caso
e mesmo com sua existência conhecida, é possível reduzir a superfície de
ataque explorada por um invasor pela limitação do tempo em que as portas
estejam abertas ou mesmo parcialmente visíveis.
Sondagem de portas
Antes de começar, é oportuno olhar mais atentamente para as portas de
rede de um servidor, assim conseguimos um panorama de referência.
Quem já usou alguma ferramenta de segurança, como a Nmap, deve estar
familiarizado com a premissa inicialmente confusa de que algumas portas
parecem estar fechadas quando de fato não estão. Ao se deparar com uma
porta aparentemente fechada, o Nmap consegue distinguir se ela está
verdadeiramente fechada ou se há um serviço escondido por trás dela.
O Nmap chama de fechadas as portas que não têm um daemon associado
a ela, porém parecem estar abertas ou, pelo menos, potencialmente
disponíveis. Se o Nmap se referir a portas filtradas, pode significar algum
tipo de firewall prevenindo acesso ao endereço IP do agressor que está
escaneando o sistema em questão. Isso tem a ver parcialmente com pacotes
TCP RST2 e também com a existência de três outros estados informados
pelo Nmap: unfiltered (não filtrado), open|filtered (aberto|filtrado) e
closed|filtered (fechado|filtrado). Mais informações acerca das diferenças
entre esses três estados podem ser obtidas em
https://nmap.org/book/man-port-scanning-basics.html.
Instalação do knockd
Agora que já conhecemos o básico, veremos como instalar um port
knocker no servidor. No decorrer da explicação, devemos considerar quais
serviços desejamos rodar de forma escondida da internet. Pode ser que
precisemos rodar um servidor web ou um servidor de emails em uma porta
não usual por um período de poucas horas, por exemplo.
Pacotes
O serviço que oferece a funcionalidade de port knock chama-se knockd.
Esse pacote é instalado de diferentes formas, dependendo do sistema.
Em derivados de Debian o pacote é instalado da seguinte maneira:
# apt-get install knockd
Em derivados Red Hat a instalação é:
# yum install knockd
Um arquivo de configuração principal controla a maioria das configurações
necessárias para o knockd. Em um servidor Debian Jessie, esse arquivo
reside em /etc/knockd.conf. A Listagem 1.1 mostra meu arquivo config
principal para vermos como o knockd funciona.
Listagem 1.1 – Arquivo de configuração principal. As sequências de portas e
(principalmente) -I INPUT foram alteradas em relação aos defaults.
[options]
UseSyslog
[openSSH]
sequence = 6,1450,8156,22045,23501,24691
seq_timeout = 5
command = /sbin/iptables -I INPUT -s %IP% -p tcp—dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 3011,6145,7298
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp—dport 22 -j ACCEPT
tcpflags = syn
Inicialização do serviço
Não se assuste ao ver uma mensagem de erro dizendo que o knockd está
desabilitado. Isto é uma precaução: até que se tenha concluído sua
configuração, o knockd não introduzirá alterações indesejadas no iptables.
No Debian Jessie a mensagem de erro sugere definir, no arquivo
/etc/default/knockd, o valor 1 para o parâmetro:
START_KNOCKD = 1
Evidentemente, isso somente deve ser feito após conferir as configurações
no mínimo duas vezes ou assegurando-se que o acesso ao serviço desejado
está funcionando conforme esperado sem o knockd.
Teste da instalação
Como estamos lidando com a segurança de um servidor, alguns testes
devem ser executados para garantir o funcionamento do knockd conforme
esperado. O ideal é ter acesso a outra máquina cliente, via internet, para
rodar alguns testes a partir dela. Para ter certeza de que o knockd abre e
fecha as portas da forma correta, gosto de fazer o teste me conectando
várias vezes ao serviço, cada vez a partir de um endereço IP público
completamente diferente. Se o acesso a uma conexão com um endereço IP
público diferente do anterior não for possível, a conexão à internet do
cliente que está fazendo o teste contra o knockd deve ser derrubada
periodicamente, fazendo com que um novo IP para teste seja alocado pelo
provedor de serviços. Alguns provedores de banda larga e de internet
móvel fazem isso após uma reinicialização – mas às vezes não; consulte seu
provedor.
Teste do iptables
Como disse antes, uso o iptables, que é, na opinião de quase todo mundo,
bastante confiável. O ideal é ter acesso físico ao servidor antes de bloqueá-
lo, pois se o estivermos operando remotamente ficaríamos trancados do
lado de fora caso criemos uma regra errada. Na eventualidade de um
problema, devemos contar com um acesso local, que independa de
conexão com a internet, como o console de uma máquina virtual, uma
interface de rede secundária na qual se possa fazer o login ou um modem
discado (dial-up) acoplado à máquina. É preciso estar ciente de que, salvo
por um teste prévio da configuração em uma máquina de desenvolvimento,
há uma chance muito grande de cometer um erro e arranjar problemas.
Mesmo tendo usado o port knocking antes, ocasionalmente ainda sou pego
de surpresa e fico sem acesso a um servidor.
Com esse alerta em mente, vamos começar olhando os comandos do
iptables. É preciso tomar cuidado ao integrar estas regras com quaisquer
outras regras anteriores. É aconselhável somente sobrescrever as regras
existentes após a realização de um backup. Em primeiro lugar, é preciso
assegurar que o servidor pode conversar com ele próprio pela interface
localhost:
# iptables -A INPUT -s 127.0.0.0/8 -j ACCEPT
É preciso agora estar seguro de que quaisquer conexões existentes são
reconhecidas e podem emitir respostas:
# iptables -A INPUT -m conntrack—ctstate ESTABLISHED,RELATED -j ACCEPT
O conntrack está sendo usado para rastrear as conexões existentes. Uma
vez inicializadas com sucesso, as conexões podem continuar a operar.
Agora, assumindo que somente a porta TCP 22 do servidor SSH vai ser
aberta e que o servidor não oferecerá nenhum outro serviço, podemos
prosseguir. Lembre-se de que, na Listagem 1.1, usamos o seguinte
comando para abrir a porta TCP 22:
command = /sbin/iptables -I INPUT -s %IP% -p tcp—dport 22 -j ACCEPT
Preste atenção a essa linha. Se usarmos a ação “append” do iptables, ou
seja, -A INPUT no comando, seremos trancados para fora, pois a regra será
inserida no final da lista de regras. Um -I de “insert” deve ser digitado para
que a regra seja introduzida na primeira posição da lista e tenha
precedência sobre as demais.
Você deve estar se perguntando o que significa a variável %IP%. O port
knocking tem inteligência suficiente para substituir a variável %IP% pelo
endereço IP da conexão no campo -s.
Agora chegamos ao ponto em que deve ser tomado muito cuidado. Não há
retorno caso as coisas não funcionem como esperado, portanto neste caso
as regras devem ter sido testadas em uma máquina virtual ou o servidor
deve poder ser acessado por caminhos alternativos. O bloqueio de todo o
tráfego entrante no servidor pode ser feito da seguinte maneira:
# iptables -A INPUT -j DROP
O comando a seguir lista todas as regras do iptables. Em condições
normais, não veremos qualquer menção à porta TCP 22 e à sua porta SSH:
# iptables -nvL
No entanto, quando fazemos login via SSH e usando o port knocking, a
regra liberando a porta 22 será vista no iptables (o tempo em que a regra
estará ativa depende do valor usado em cmd_timeout; um valor muito
baixo fará com que a regra apareça muito brevemente na lista) se o login
tiver sido feito com sucesso.
Se houver problemas a esta altura, continue lendo: veremos mais adiante
algumas formas de testar a configuração e aumentar os níveis de logging.
Caso contrário, temos um servidor cujas portas são todas informadas como
não existentes, tornando assim o servidor invisível, conforme mostrado na
Figura 1.1.
Figura 1.1 – O Nmap parece considerar que não existe máquina naquele
endereço IP.
Outras considerações
Há alguns aspectos relacionados ao port knocking que podem ser úteis.
Vamos dar uma olhada neles agora.
Pesquisa de problemas
O comando tail -f logfile.log permite examinar arquivo de log do
port knocking em tempo real. Com ele, podemos observar diversos
estágios do processo sendo escritos no log, o que inclui o fato de uma porta
válida ter sido acessada e, muito importante, se as portas configuradas
foram “batidas” na sequência correta ou não.
Podemos aumentar os níveis de logging produzidos pelo knockd ativando a
opção de depuração. Abra o arquivo /etc/init.d/knockd (com cuidado
para não modificar nada) e procure pela linha OPTIONS. É possível
acrescentar um caractere D maiúsculo (Shift+d) em quaisquer valores
existentes nesta linha, conforme mostrado a seguir:
OPTIONS = "-d -D"
O logging adicional deve ser desativado depois da realização do
diagnóstico e da solução do problema, para evitar perda desnecessária de
espaço em disco. O -d significa que o knockd roda como um daemon,
caso alguém esteja se perguntando. Ele deve ser deixado como está para
operação normal.
Retornemos ao cliente por um momento. O nível de detalhes na saída
também pode ser aumentado, algo que o cliente “knock” gera pelo
acréscimo de uma opção -v. Em conjunto com a opção de depuração no
servidor, isso deve fornecer informação proveitosa dos dois lados da
conexão.
Considerações de segurança
Quando as informações associadas a um servidor são divulgadas, devemos
ter em mente que é necessário solicitar ao provedor de conexão à internet
para não publicar diretamente seu endereço IP público, seja por DNS
direto, seja por DNS reverso. Seu endereço IP deve aparecer como não
usado ou não alocado, ficando dessa forma invisível.
Mesmo em serviços públicos como HTTP, as versões dos daemons sendo
utilizadas devem ser ofuscadas. A forma corriqueira de fazer isso no
servidor mais popular da web, o Apache, é alterar o ServerTokens para
“Prod” e configurar ServerSignature para “Off”. Estas são alterações de
configuração altamente avançadas, porém podem significar que um ataque
automatizado ignore seu servidor quando um novo ataque de dia zero
(zero-day exploit) é descoberto, pois o número de versão do seu Apache
não estava no banco de dados do agressor.
Outro aspecto a ser considerado é discutido na documentação do knockd.
Ela menciona que se você usar as opções -l ou --lookup para resolver
nomes de máquina em suas entradas de log, pode estar incorrendo em um
risco de segurança. Se isso for feito, há uma chance de vazamento de
informações para um invasor, que pode ter condições de determinar a
primeira porta de uma sequência se conseguir capturar o tráfego DNS do
servidor.
Sequências efêmeras
Que tal usar uma abordagem diferente para as sequências de knocking?
Também é possível usar o port knocking com uma lista predefinida de
sequências de porta que expiram depois que foram usadas apenas uma vez.
Consultando novamente a Listagem 1.1 e o arquivo de configuração
principal, podemos acrescentar, caso assim desejemos, a opção a seguir às
seções open e close para habilitar as sequências de evento único:
[openSSH]
One_Time_Sequences = /usr/local/etc/portknocking_codes
Se a linha sequence for removida da Listagem 1.1 e substituída por esse
código, o knockd então seguirá as sequências conforme o arquivo
especificado no caminho.
O knockd lida com as sequências de tempo único de uma forma não usual.
Ele lê a próxima sequência disponível do arquivo e comenta aquela linha,
seguida de uma conexão realizada com sucesso com um knock válido. Ele
simplesmente acrescenta um caractere # ou hash ao início da linha que
tiver a sequência presente. A próxima conexão aciona a mesma sequência.
A documentação estabelece que deve ser deixado um espaço no início de
cada linha. Caso contrário, quando o caractere # for acrescentado ao início
da linha, pode-se pensar que ele foi sobrescrito de forma não intencional,
significando então a ocorrência de um bloqueio.
No arquivo de sequências, podemos acrescentar uma sequência por linha.
Esse arquivo segue o mesmo formato que na opção sequences dentro do
arquivo de configuração principal.
A documentação também ressalta que podem ser inseridos comentários
colocando na frente deles o caractere #, porém isso pode acarretar
problemas (como ficar com o acesso ao servidor bloqueado) se o arquivo
de sequências for editado enquanto o knockd ainda estiver rodando.
Uma vez compreendidos os recursos básicos do knockd, é uma excelente
hora de experimentá-lo. Durante o teste, podem ser digitados números de
telefone ou alguma outra sequência de números que possa ser memorizada
depois, de modo a garantir que não estamos lidando continuamente com
uma lista insegura. Por exemplo, uma rotatividade entre cinco números
telefônicos pode ser considerada, dividindo-os entre números de porta
válidos.
Resumo
Além de tornar um servidor invisível, expliquei como esse servidor aparece
na internet antes do lançamento de um ataque. Para que um servidor seja
totalmente ofuscado com o uso do port knocking, o uso de informações
públicas, como entradas de DNS reverso, deve ser pensado com muito
cuidado, o que pode levar à desistência de um endereço IP como se ele
estivesse em uso. O uso de NAT para esconder um servidor e fazer a troca
dinâmica periódica do endereço IP pode também ser considerado,
deixando que somente administradores conheçam qual endereço IP está
em uso em um determinado momento por meio de um nome de usuário
secreto, publicado de forma sigilosa em DNS em um Nome de Domínio
não usual.
Há muitas outras maneiras de proteger um servidor. De qualquer modo,
espero ter dado informações suficientes para fazer o leitor considerar que
tipo de informação é vazada publicamente e que possa ser potencialmente
usada em ataques futuros, bem como para esconder um servidor caso seja
necessário fazê-lo.
1 N. do T.: Não traduzimos door-knock por ser considerado jargão técnico, mas, resumidamente,
seria como aquelas senhas que combinamos com os amigos ou familiares para avisar quem está
batendo à porta ou tocando a campainha. Por exemplo, se ouvirmos um toque curto e três longos
na campainha, já sabemos que é o primo trazendo a pizza.
2 N. do T.: O autor considera que o leitor tem uma boa base teórica a respeito dos mecanismos de
roteamento IP, conexão TCP, especialmente o processo de sincronismo inicial (three-way
handshake), e comunicação UDP. Sugerimos ao leitor fazer uma revisão prévia desses conceitos
para melhor entendimento deste capítulo.
CAPÍTULO 2
Coloque impressão digital em seus arquivos
Rootkits
Vamos agora para uma abordagem diferente de impressão digital de
arquivos.
Se o interesse for proteger os arquivos contra rootkits (contendo um código
que permita a algum estranho acessar ou controlar as máquinas), deve ser
considerada também uma excelente ferramenta denominada Rootkit
Hunter (também chamada de rkhunter;
http://rkhunter.sourceforge.net).
Por ocasião da instalação, o manual do Rootkit Hunter (caçador de
rootkits) alerta que provavelmente não será possível executá-lo se houver
uma tentativa de rodar o software em um sistema supostamente
comprometido e que não tenha os comandos a seguir (comuns na maioria
dos sistemas): cat, sed, head ou tail.
Ressalto esse fato por uma boa razão: esses comandos podem ser
corrompidos ou perdidos em uma máquina invadida. Se o Rootkit Hunter
foi instalado para caçar arquivos infectados e houver a constatação da
invasão do sistema, é realmente necessário recompor a máquina. Não
assuma que os reparos feitos deste ponto em diante tornarão a máquina
segura o suficiente para utilização posterior. Isso simplesmente não vale a
pena devido ao tempo gasto no futuro em novos reparos na máquina.
Em outras palavras, o software deve ser usado para identificar ataques
bem-sucedidos com exatamente esta finalidade: identificação. Além disso,
devemos considerar sempre a necessidade de reconstruir todo o sistema em
vez de reaproveitar o antigo. Pela minha experiência, rootkits traiçoeiros
grudam como cracas no sistema de arquivos. Logo se descobre (como já
ocorreu comigo no passado) que o tempo gasto correndo atrás do próprio
rabo, tentando limpar o sistema, é superior ao tempo realmente empregado
para instalá-lo do zero.
Deixando o “blábláblá” de lado, vejamos como se usa o Rootkit Hunter.
Para instalar esse software sofisticado, os comandos a seguir podem ser
usados.
Em derivados do Debian:
# apt-get install rkhunter
Em derivados do Red Hat:
# yum install rkhunter
Assumindo que sua instalação não apresenta qualquer erro, alguns poucos
comandos simples podem ser executados para começar. Os comandos a
seguir preenchem o banco de dados das propriedades dos arquivos:
# rkhunter-propupd
Em seguida, para escanear qualquer novo software sendo instalado e para
fazer a ativação após a atualização de software, a opção APT_AUTOGEN deve
ser habilitada com yes no arquivo /etc/default/rkhunter. Verifiquei
isso somente em derivados do Debian com Apt Package Manager; pode
haver uma opção diferente em derivados do Red Hat.
Feitas essas alterações, a primeira execução do Rootkit Hunter pode ser
realizada da seguinte maneira:
# rkhunter—check
Observe que há diferenças sutis entre versões ou distribuições. Caso
ocorram erros, tente adicionar -c ou --checkall.
Periodicamente, a lista de ameaças do rkhunter também pode ser
atualizada com o comando a seguir (uma tarefa cron específica pode ser
criada, se desejar) para manter o registro das últimas ameaças:
# /usr/local/bin/rkhunter—update
A Figura 2.2 mostra uma saída abreviada gerada após a execução desse
comando. A saída detalha os testes iniciais realizados pelo software.
O Rootkit Hunter presta atenção aos diretórios-chave contendo arquivos
executáveis (/usr/sbin neste exemplo). Esses são exatamente os tipos de
arquivos binários (entre muitos outros) que se tornam infectados por um
rootkit.
Por um momento, pense nos gregos e na alegoria do Cavalo de Troia. Além
dos rootkits que infectam binários de forma imediata, um trecho de código
pode permanecer dormente por um determinado período de tempo até ser
executado por um usuário legítimo ou por uma tarefa agendada. Em
decorrência disso, ocorre o comprometimento do sistema.
Configuração
Para configurar o Rootkit Hunter, basta editar seu extenso arquivo de
configuração em /etc/rkhunter.conf.
Para receber relatórios noturnos sobre a integridade da máquina, é
necessário editar apenas dois parâmetros de configuração: o endereço de
email do destinatário e um ajuste caso o comando-padrão mail não
funcione em seu sistema por default.
Dentro do arquivo de configuração, observe as linhas destacadas a seguir,
descomente-as e ajuste conforme suas necessidades:
#MAIL-ON-WARNING=me@mydomain root@mydomain
#MAIL_CMD=mail -s "[rkhunter] Warnings found for ${HOST_NAME}"
A primeira linha, após ser descomentada, especifica para onde os relatórios
devem ser enviados (endereços múltiplos devem ser separados por um
espaço). A segunda linha é referente ao comando mail e a linha de assunto
trata dos relatórios de email enviados a esses destinatários.
Para conferir se essas alterações apresentam um desempenho correto e
verificar a caixa de entrada do seu email, basta rodar novamente o software
com rkhunter—check.
Para inspecionar a tarefa cron que dá suporte ao agendamento quando
esses relatórios forem gerados, o arquivo /etc/cron.daily/rkhunter
pode ser consultado. Por default, cron.daily roda geralmente no período
entre 01:00 e 05:00 da madrugada todos os dias, em muitas distribuições.
Se desejar alterar a forma como os emails são mostrados, as seguintes
linhas devem ser localizadas no arquivo cron.daily:
if [ -s "$OUTFILE" -a -n "$REPORT_EMAIL" ]; then
(
echo "Subject: [rkhunter] $(hostname -f)—Daily report"
echo "To: $REPORT_EMAIL"
Como sempre, a prudência ensina que deve ser criada uma cópia desse
arquivo antes de alterá-lo.
Retornemos aos resultados que gerei com a execução do Rootkit Hunter.
Na Figura 2.3 alguns dos rootkits pesquisados pelo Rootkit Hunter podem
ser visualizados.
Figura 2.3 – Lista parcial de alguns dos rootkits pesquisados pelo Rootkit
Hunter.
Como pode ser visto nas Figuras 2.3 e 2.4, há diversas facetas pesquisadas
pelo Rootkit Hunter; as verificações são bastante abrangentes.
Falso-positivos
Caso receba quaisquer falso-positivos, você pode colocá-los na whitelist
dentro do arquivo de configuração /etc/rkhunter.conf.
Caso o volume de alarmes falsos se torne problemático, podemos fazer isso
descomentando uma linha de configuração que case com um diretório
completo dentro do arquivo de configuração principal da seguinte forma:
ALLOWHIDDENDIR = /dev/.initramfs
Se o Rootkit Hunter suspeitar equivocadamente que um dos binários foi
substituído por um script, o aviso pode ser removido com a opção:
SCRIPTWHITELIST = "/usr/sbin/lsof"
Em arquivos individuais o seguinte ajuste de configuração pode também
ser usado:
ALLOWDEVFILE = "/dev/.udev/rules.d/99-root.rules"
Tenha em mente que quaisquer arquivos ou pastas (aqueles com nome
começando com um ponto) são quase sempre suspeitos aos varredores do
sistema de arquivos. A Figura 2.5 mostra outra parte dos resultados da
varredura do Rootkit Hunter referentes a verificações da existência de
quaisquer arquivos maliciosos ocultos.
É evidente que as verificações abrangentes feitas pelo Rootkit Hunter estão
bem consideradas. Além do sistema de arquivos e da tabela de processos,
ele também procura anomalias na rede, como pode ser visto na Figura 2.6.
Bem projetado
Os desenvolvedores do Rootkit Hunter o descrevem como uma ferramenta
“que roda no host, passiva, pós-incidente, orientada a caminhos do sistema
de arquivos”. Caso o leitor esteja curioso, o termo “passiva” significa que o
software pode rodar de forma agendada ou manual. Já “orientada a
caminho” (“path-based”) significa que ele lida somente com arquivos, não
operando heuristicamente como um verificador de vírus.
Há uma seção na parte inferior da documentação incluída com o rkhunter
que gostei muito de ler. É uma cartilha elementar muito bem escrita para
todos os novatos em segurança ou para os usuários com mais experiência
buscando apenas uma revisão de conhecimentos.
Ela primeiro ressalta que, antes de o agressor iniciar um ataque, há sempre
alguma forma de reconhecimento ou pesquisa prévia, portanto devemos
prestar muita atenção ao que aparece nos arquivos de log. Em um dos
meus servidores, lembro de ter preparado um script que detectava
traceroutes e tráfego ICMP.
Repetindo o anteriormente citado, o manual prossegue dizendo que esta
ferramenta não é um substituto para o aumento da segurança
(“hardening”) de uma máquina. Não a considere dessa forma, mas sim
como uma ferramenta auxiliar na identificação de problemas.
É interessante observar que a documentação do Rootkit Hunter também
indica um de seus competidores, a excelente ferramenta chkrootkit, uma
encarnação mais antiga do rkhunter. Conforme o manual sugere, o uso de
somente uma ferramenta do mesmo tipo nem sempre é suficiente para
obter toda a informação desejada. Portanto, para trabalhar de forma mais
completa, é benéfico rodar ambas, chkrootkit e o rkhunter. A dica (rodar
mais de uma ferramenta do mesmo tipo) é importante e deve ser aplicada a
todas as facetas da segurança.
Por fim, o manual discorre sobre o que fazer ao perceber o
comprometimento de uma máquina e você não tiver o conhecimento
necessário para lidar com um ataque bem-sucedido. Além de acessar
www.cert.org, talvez seja interessante ir para
www.linuxsecurity.com.br/info/IDS/intruder_detection_checklist.html
em que há uma lista de passos a serem seguidos para reagir a um ataque
online.
Os profissionais muito experimentados nesses ataques recomendam que se
deve considerar para quais autoridades o ataque deve ser informado e
enviar um relatório assim que possível – em vez de esperar por semanas ou
meses – no caso de que algo possa ser feito para evitar esses
comprometimentos. Como sempre o bom senso deve ser a tônica.
Resumo
Neste ponto, o leitor já tem o conhecimento necessário para colocar
impressões digitais nos objetos do sistema de arquivos. Com isso, é
possível comparar rapidamente as somas MD5 anteriores para ver se os
arquivos foram alterados e também rodar o Rootkit Hunter, todas as noites
ou periodicamente. A parte boa dos verificadores de rootkit é a
tranquilidade que também oferecem pelo fato de a varredura programada
destacar falhas de configuração. A correção pode ser então realizada antes
de causar problemas posteriores de segurança.
De todo o exposto, há duas regras a ter em mente:
• Mantenha sempre as somas MD5 gravadas (ou quaisquer outros hashes)
usando algum recurso de segurança (criptografia e proteção por senha) e
desvinculadas do servidor.
• Não confie em ferramentas rootkit para reduzir seus esforços pós-
evento; use-os apenas para identificar problemas. A partir daí, faça uma
análise para concluir como um comprometimento foi possível antes de
partir para a reconstrução da máquina. Não há sentido em gastar um
bom tempo na reconstrução da máquina para, logo em seguida, ser
invadido através da mesma falha de segurança. A frequência com que
isso ocorre é apavorante.
Quando serviços menos críticos estiverem rodando, geralmente não é
preciso muito planejamento nem muito trabalho para garantir a segurança
de uma máquina conectada à internet, mesmo quando tarefas demoradas
são introduzidas no sistema – como, por exemplo, a geração de relatórios
noturnos listando as alterações no sistema. Se forem tomadas precauções
iniciais já no estágio de construção da máquina, os hackers na internet
podem ser mantidos à distância e os profissionais de TI podem trabalhar
em paz.
CAPÍTULO 3
Netcat no século 21
História
Ao longo dos anos houve diversas implementações do netcat. A versão
original para Unix/Linux foi escrita em 1995, e em 1998 uma versão
Windows apareceu devido à sua popularidade. Uma vez li que uma
pesquisa conduzida pela Nmap Project (https://nmap.org) descobriu
que, depois de sua própria ferramenta de segurança, o Nmap, seus
usuários optavam pelo netcat como segunda opção.
A funcionalidade do netcat ajudou também a alavancar sua popularidade
em áreas ilícitas. Assim, além do uso em atividades de white hat bem-
intencionadas, ele é bastante usado em reconhecimento de ataques (e nos
próprios ataques). Em decorrência disso, não se espera encontrar versões
completas (modernas) do netcat na infraestrutura das empresas, atendendo
a preocupações de segurança e devido também a seus pacotes serem
colocados como ameaça em listas negras.
Vou tentar explicar de forma sucinta alguns dos parentescos do netcat. É
fácil fazer confusão porque o netcat original (cujo binário executável é
chamado de nc) foi reformulado pelo Nmap Project, que se refere a ele
como o “Netcat for the 21st Century” (Netcat do século 21). O resultado
da reformulação foi um binário denominado ncat. A página principal do
ncat obedientemente reconhece a versão original com o seguinte
comentário final:
O Netcat original foi escrito por *Hobbit* hobbit@avian.org. Enquanto
o Ncat não foi escrito usando qualquer código do Netcat “tradicional”
(ou qualquer outra implementação), o Ncat é definitivamente baseado
no Netcat, em similaridade e em funcionalidade.
Essa versão do netcat (ncat) alega (modestamente) ser capaz de
“concatenar e redirecionar sockets”, porém esta é uma subavaliação muito
simplista de seu conjunto de funcionalidades.
Há uma versão do ncat disponível no Red Hat Enterprise Linux (RHEL) 7,
por exemplo, e suspeito que, além do netcat original (nc), ele foi
disponibilizado em outros releases em diversas encarnações ao longo dos
anos. Há também uma versão do netcat original (incluída por default nas
compilações Debian Jessie e cujo binário é também chamado de nc),
alegando que suas habilidades são o “canivete suíço TCP/IP”. A página do
RHEL 7 a seguir ressalta algumas das poucas diferenças entre essas duas
encarnações: https://access.redhat.com/documentation/en-
US/Red_Hat_Enterprise_Linux/7/html/Migration_Planning_Guide/sect-
Red_Hat_Enterprise_Linux-Migration_Planning_Guide-
Networking.html#sect-Red_Hat_Enterprise_Linux-
Migration_Planning_Guide-Networking-
New_network_configuration_utility_ncat.
Uma visita a essa página permite ver que diversas opções de linha de
comando sofreram alterações. Algumas foram suprimidas e em outras o
ncat mais recente simplesmente alterou seu significado.
É importante observar também que sem o acesso com privilégios de
usuário de root, a taxa de sucesso entre as versões pode variar, portanto o
leitor não deve ficar muito frustrado se tiver de fazer um certo número de
tentativas para fazer o netcat funcionar da forma esperada. Aqui está um
excelente artigo mostrando o procedimento a adotar quando a versão do
netcat não suporta as opções ?e ou ?c para rodar um shell: https://pen-
testing.sans.org/blog/2013/05/06/netcat-without-e-no-problem.
De volta à página RHEL 7 mencionada antes, ela afirma, de forma um
tanto convicta, que o ncat mais recente não inclui certas funcionalidades
presentes no seu parente, o netcat. O motivo talvez seja o fato de essas
funcionalidades simplesmente não serem assim tão úteis na internet
moderna. O site do Nmap Project na web inclui a seguinte afirmação:
O Ncat acrescenta muitas capacidades não encontradas no nc original
da Hobbit, incluindo suporte SSL, conexões proxy, IPv6 e mediação de
conexões. O nc original continha um único scanner de portas, porém a
omitimos do Ncat porque temos uma ferramenta preferencial para essa
função.
Naturalmente, eles estão se referindo à sua famosa ferramenta de
escaneamento de portas Nmap, sugerindo que ela acompanhe o ncat. Em
minha opinião, elas têm um poder enorme quando operam juntas, e minha
sugestão é explorar o considerável conjunto de funcionalidades incluídas
no Nmap.
Voltemos ao netcat. Agora, com o leitor já devidamente confuso, vou
aumentar ainda mais a confusão dizendo que houve também duas versões
do netcat original (refiro-me ao nc e não ao ncat neste caso). O netcat
verdadeiramente original foi escrito pelos programadores da Avian
Research em 1995, e a última versão foi liberada como versão 1.10 em
1996. Uma versão GNU do netcat foi então liberada
(http://netcat.sourceforge.net), cuja versão mais recente, a 0.7.1, foi
liberada em janeiro de 2004. Vale a pena mencionar os dois netcats “nc”
porque o leitor pode ter dificuldades ao usar as mesmas opções de linha de
comando entre as duas diferentes versões. Caí nesta armadilha no passado,
o que me causou muita complicação quando a documentação não casava
com o comportamento do software.
A própria página netcat do Nmap Project
(http://sectools.org/tool/netcat) revela também que houve ainda
mais derivados, incluindo: socat (www.dest-unreach.org/socat),
Cryptcat (http://cryptcat.sourceforge.net), pnetcat
(http://stromberg.dnsalias.org/~strombrg/pnetcat.html) e sbd (um
site informativo não oficial pode ser encontrado em www.question-
defense.com/2012/04/09/sbd-backtrack-5-maintaining-access-os-
backdoors-sbd).
Pacotes de instalação
Para fins de clareza, o Debian Linux e, portanto, o Ubuntu Linux, usam os
nomes dos pacotes mostrados na Tabela 3.1. Em derivados do Red Hat, o
nome de pacote netcat instala, na verdade, uma versão do nc antigo:
# yum install netcat
Para instalar o ncat do Nmap Project, o pacote correto seria:
# yum install nmap-ncat
Para mim, a instalação de um pacote e a certeza de estar lendo a página
principal correta para aquele pacote (caso duas versões do netcat estejam
instaladas na mesma máquina) são garantias de sucesso.
Tabela 3.1 – Nomes dos pacotes Debian e Ubuntu
Nome do pacote Descrição
Um pacote “dummy” (fictício) para fins de compatibilidade, que pode ser removido
netcat
sem problemas
netcat-
O netcat original em versão OpenBSD com suporte para IPv6, proxies e sockets Unix
openbsd
netcat- Pacote original de Hobbit, que não tem muitas das funcionalidades encontradas no
traditional netcat-openbsd
Uma reformulação do netcat original com suporte IPv6 e suporte aprimorado para
netcat6
UDP
nmap Este é o pacote para quem deseja usar o ncat do projeto Nmap no Debian/Ubuntu
Para evitar confusões, vou me concentrar no ncat (e no comando ncat) em
contraposição ao netcat (e, portanto, no comando nc). De agora em diante,
vou me referir ao ncat e ao netcat de forma intercambiável – ou,
naturalmente, ao ncat de forma específica caso seja necessário esclarecer
melhor.
Para começar
Vamos ver o que o equivalente do século 21 do netcat (estou falando do
ncat, lógico) pode fazer, começando com algumas noções básicas. De
forma ousada, o Netcat alega conter funcionalidades poderosas capazes de
manipular dados (tanto leitura quanto escrita de dados) em uma rede via
linha de comando. Ele tem uma alta confiabilidade e pode operar tanto
com TCP quanto com UDP (também trabalha bem com o IPv6). Pode fazer
coisas impressionantes com conexões SSL (Secure Sockets Layer) e pode
também trabalhar com proxies – variantes “CONNECT” SOCKS4 e
HTTP.
A julgar pelas excelentes práticas de programação envolvidas na ferramenta
de segurança Nmap, a qualidade da programação do ncat deve ser também
muito alta. A documentação ncat do Nmap faz questão de afirmar que usa
não somente um código totalmente reescrito (e não emprestado da versão
original), mas também emprega bibliotecas de rede completamente
testadas em condições reais.
Tendo mencionado proxies HTTP, vou começar usando o netcat como um
navegador web. A digitação do comando seguinte, junto com um site da
web arbitrário que se deseje visitar, possibilita a conexão à porta 80 TCP:
# ncat -C www.chrisbinnie.tld 80
Assim que tiver digitado esse comando e pressionado a tecla Enter, será
necessário digitar o seguinte texto, seguido do pressionamento de Enter
por duas vezes:
GET / HTTP/1.0
É bom avisar que, caso isso não seja feito com rapidez, o comando tem sua
temporização vencida e deve ser feita uma nova tentativa. Caso tenha
havido antes uma consulta HTML pela linha de comando, não será
surpresa se depois disso for apresentado um grande volume de informações
rolando para cima na tela. Caso haja interesse, a opção -C coloca um
Carriage Return e um Line Feed (CRLF) no conjunto para garantir a
compatibilidade com alguns protocolos de rede.
O netcat pode ser usado também como um daemon que “escuta”, ou seja,
age como um servidor e não como um cliente, como no exemplo anterior.
Há diversas formas de invadir servidores, e uma maneira de manter o
acesso aberto para uma visita posterior é deixar o netcat escutando em uma
porta obscura não percebida pelo administrador de sistemas.
Mais adiante discorreremos sobre isso; por enquanto o foco será o HTTP.
A documentação do ncat fornece um excelente exemplo de como converter
um binário netcat em um servidor web básico. Para começar, um arquivo
simples deve ser criado. Porém, a extensão .html não deve ser usada
porque o arquivo não é HTML puro, mas sim a metade de uma
conversação HTTP. O arquivo index.http será utilizado com o conteúdo
mostrado na Listagem 3.1.
Listagem 3.1 – Metade de uma conversação HTTP salva no arquivo index.http
HTTP/1.0 200 OK
<HTML>
<BODY>
Nothing to see here, move along.
</BODY>
</HTML>
Conforme mostrado na Listagem 3.1, o código é basicamente HTML,
porém a linha superior (que não é HTML) serve para que o cliente web
visitante saiba que o nosso servidor improvisado acolheu sua solicitação.
Em seguida, o netcat deve ficar pronto para escutar conexões e apresentar
o arquivo quando solicitado. O comando é:
# ncat -l 127.0.0.1 80 < index.http
A propósito, é possível servir todo tipo de outros conteúdos usando o
netcat. Caso o leitor tenha algum dia digitado manualmente uma
conversação SMTP pela linha de comando, provavelmente não ficará
surpreso em descobrir que a opção <CR><LF> (ou seja, a opção –C) opera
da mesma forma nas conversações de email.
Transferência de arquivos
Vamos pensar por um momento no envio de um arquivo de um host para
outro apenas usando netcat em cada ponta. Para isso, não são necessários
daemons SFTP complexos ou aplicativos que exigem muitos recursos.
Vamos chamar as duas máquinas de exemplo de Lionel e Luis, com um
arquivo sendo passado de Lionel para Luis. Em Luis, o seguinte comando é
executado:
Luis> # ncat -l 1234 > bootstrap.pp
A chave -l simplesmente instrui o netcat para “escutar” o tráfego de
entrada. O tráfego está sendo escutado na porta TCP 12341, e os dados de
entrada estão sendo enviados para um arquivo denominado
bootstrap.pp; esse arquivo é um puppet manifest, cuja ação de copiar e
colar entre hosts não é desejada porque é longa e complexa. Agora, com
Luis pronto e esperando a passagem dos dados, o envio de dados de Lionel
é determinado por:
Lionel> # ncat --send-only Luis 1234 < bootstrap.orig
Quando esse comando já tiver rodado em Lionel, a instância netcat em
Luis é finalizada. Antes que Luis encerre, ocorre a transferência do
conteúdo do arquivo bootstrap.orig em Lionel para o arquivo
bootstrap.pp em Luis — uma ação simples e engenhosa. As únicas
possibilidades de algo dar errado são, primeiro, as versões (use somente o
ncat para simplificar), e segundo, o firewall. Abra com muito cuidado as
portas necessárias no firewall caso tenha problemas.
A documentação ncat mostra também como o comando tar pode ser
usado para mover múltiplos arquivos. Considere este exemplo:
Luis> # ncat -l | tar xzv
Lionel> # tar czv <list of files> | ncat --send-only Luis
Novamente, Lionel envia dados para Luis, dessa vez por meio do comando
tar nas duas pontas. Meu exemplo favorito é usar compressão para
acelerar a transferência (arquivos pesados também podem ser movidos) e,
naturalmente, transferir menos dados. Observe este método usando
compressão:
Luis> # ncat -l | bzip2 -d > massive.file.bz
Lionel> # cat massive.file.orig | bzip2 | ncat --send-only Luis
Nesse exemplo, estamos utilizando o confiável comando bzip2 para a
compressão e duplicando massive.file.orig em Lionel para um arquivo
denominado massive.file.bz em Luis. Observe que está sendo usado o
comando cat para ler massive.file.orig e para conduzi-lo por bzip2;
isso não é um erro de digitação.
Exemplo de bate-papo
Vamos nos divertir um pouco mantendo um bate-papo com um usuário de
outro computador. O leitor deve ter visto o comando wall no passado,
aplicado a todos os usuários logados. O netcat pode ser usado para bate-
papo bidirecional. Capture uma porta na máquina receptora (Luis
novamente) e polidamente peça para que o netcat escute, conforme
explicado a seguir:
Luis> # ncat -l 1234
Depois execute o comando a seguir. Após executado, qualquer coisa que o
leitor digitar em Lionel (pressionando a tecla Enter ao final de cada linha
para enviá-la) será espelhado no console de Lionel e vice-versa.
Lionel> # ncat Luis 1234
No fragmento seguinte, pode ser visto como uma comunicação se parece a
partir da perspectiva de Lionel.
# ncat 127.0.0.1 1234
Quer ouvir minhas duas regras para ter sucesso?
Claro!
Regra número 1: nunca conte às outras pessoas tudo o que sabe.
Certo, e qual a segunda?
Câmbio! Alguém na escuta? Caiu a ligação?
Esse exemplo mostra uma das muitas funcionalidades não esperadas
incluídas no netcat. Vou deixar para o leitor a chance de explorar essa
funcionalidade e continuar examinando algumas das outras opções
disponíveis. O netcat é caracterizado por uma superabundância em seu
conjunto de funcionalidades, tantas que não é possível abordar todas neste
livro.
Encadeamento de comandos
Uma das funcionalidades interessantes incluídas no ncat (porém não no
nc) é a capacidade de encadear múltiplas instâncias em um único
comando. Isso torna o ncat muito versátil – uma saída de comando do
netcat pode ser simplesmente conectada à outra, ao estilo Unix. Vamos ver
um exemplo existente na documentação do netcat. Para a tarefa a seguir,
será introduzida a máquina “Neymar” como terceiro host. Lionel ainda é o
emissor e, neste cenário, Luis é o homem no meio (man in the middle).
Reserve um tempo para analisar estes comandos:
Neymar> # ncat -l 1234 > my_new_big_file.txt
Luis> # ncat -l 1234 | ncat Neymar 1234
Lionel> # ncat --send-only Luis 1234 < lengthy_file.txt
Lionel está transferindo seu longo arquivo para Luis, que por sua vez
encadeia os dois comandos netcat juntos com o objetivo de encaminhar o
arquivo para Neymar. Este triunvirato trabalha bem, especialmente se Luis
não puder falar diretamente com Neymar devido a um firewall ou ao
roteamento.
No entanto, a documentação aponta um problema neste cenário: Neymar
não consegue responder para Lionel. Como estamos falando do poderoso
netcat, há uma alternativa. Quando olho para esse exemplo, penso
imediatamente nos ataques realizados com o objetivo de obter ganhos
indevidos (tenho certeza de que o leitor vai se defrontar com isso em algum
momento). Vejamos agora o seguinte conjunto de comandos:
Neymar> # ncat -l 1234 > newlog.log
Luis> # ncat -l 1234 --sh-exec "ncat Neymar 1234"
Lionel> # ncat --send-only Luis 1234 < logfile.log
No meu entendimento, o assustador nesse exemplo é a opção -sh-exec,
que executa um novo comando shell quando Luis estiver recebendo dados.
Imagine o estrago causado com essa opção quando alguém estiver
habilitado a emitir qualquer comando shell. Nesse exemplo, quando Luis
recebe uma conexão, ele gera uma nova instância netcat e passa a controlar
as entradas e as saídas das comunicações entre Lionel e Neymar. Isso é
muito sofisticado.
Aqui está um exemplo de encaminhamento de portas extraído da
documentação, tratando novamente com HTTP, em que um comando
shell pode ser executado para encaminhamento de tráfego:
# ncat -l locahost 80 --sh-exec "ncat www.chrisbinnie.tld 8100"
Os dados são simplesmente encaminhados para a porta 80 TCP, da
máquina local para outro host na porta 8100 TCP.
Comunicações seguras
Havíamos mencionado o SSL anteriormente e a forma como o netcat pode
interagir até mesmo com tráfego criptografado, mesmo sendo esta uma
possibilidade preocupante a ser considerada. Vou iniciar esta seção com
um exemplo de como o netcat pode criptografar seu próprio tráfego. A
chave -C será usada novamente (o que às vezes é chamado de modo
conexão – connect mode):
# ncat -C --ssl ssl.chrisbinnie.tld 443
Estamos supondo aqui que a máquina confiável, ssl.chrisbinnie.tld,
está rodando um servidor SSL na porta 443 TCP e, portanto, pode ser feita
uma conexão a ela. Surpreendentemente, mesmo para servidores SSL
usando certificados de autenticação, o poderoso netcat pode ser muito útil.
Basta apontar o netcat para um local do certificado PEM e dos arquivos de
chave privada, usando respectivamente as opções --ssl-cert e --ssl-key
dentro do comando. As duas opções podem ser apontadas para o mesmo
arquivo, se desejar.
Um ponto importante na troca de certificados, além de criptografar as
comunicações, é o ato de confirmar (por meio de um selo de aprovação
emitido por um serviço de terceiros) que a identidade do servidor SSL é
válida. O netcat tem capacidade para processar essa requisição pelo uso do
comando:
# ncat -C --ssl-verify ssl.chrisbinnie.tld 443
De acordo com a documentação, o netcat pode verificar os certificados SSL
da seguinte forma:
A verificação é realizada usando o pacote de certificados ca-bundle.crt
incluído no Ncat, além de quaisquer certificados confiáveis que o
sistema operacional possa fornecer. Caso deseje verificar uma conexão a
um servidor cujo certificado não é assinado por uma das autoridades de
certificação default, o leitor deve usar o --ssl-trustfile para nomear
um arquivo contendo certificados confiáveis. O arquivo deve estar no
formato PEM. (https://nmap.org/ncat/guide/ncat-ssl.html)
Os documentos oferecem a sintaxe correta para um comando SSL:
# ncat -C --ssl-verify --ssl-trustfile <custom-certs.pem> <servidor> 443
Agora que podemos confirmar à qual máquina estamos conectados, vamos
ver outra função SSL disponível no netcat. Ela tem muitas aplicações, que
exploraremos mais adiante.
A função é descrita como tendo a capacidade de “desempacotar” SSL. A
documentação sugere que o netcat pode ajudar caso haja a tentativa de
coletar emails de um servidor de email com SSL, porém sem dispor das
capacidades SSL no cliente de email.
Para começar, o cliente de email mencionado é apontado para o localhost,
a máquina local, cujo endereço normalmente é IP 127.0.0.1. Com o netcat
escutando localmente na porta 143 TCP (a porta normalmente usada para
comunicações IMAP não criptografadas), o tráfego pode ser encaminhado
para a porta criptografada no servidor de email, porta 993 TCP, desta
forma:
# ncat -l localhost 143 --sh-exec "ncat --ssl mail.chrisbinnie.tld 993"
Esse método pode ser usado em qualquer protocolo que usa dois hosts,
menos o HTTP, por exemplo, e não terá um bom desempenho quando
múltiplos hosts estiverem envolvidos.
O netcat pode também funcionar como um servidor SSL. É necessário
fornecer um certificado que, ao contrário do exemplo anterior, pode ser
verificado por clientes visitantes.
Se um arquivo de certificação e uma chave privada não forem fornecidos –
e usando as mesmas opções de antes (--ssl-cert e --ssl-key) –, o netcat
gera isso automaticamente para o usuário. O netcat pode ser inicializado
usando a opção -l (ou seu equivalente --listen) desta maneira:
# ncat -v --listen –ssl
Como pode ser visto na Figura 3.1, o flexível netcat gera uma chave
temporária para iniciar com mais facilidade.
Executáveis
Além de lidar com a criptografia, um comando também pode ser
executado no shell quando uma conexão for recebida. É desnecessário
dizer que sempre devem ser consideradas as implicações de segurança com
potencial desastroso ao executar os comandos a seguir. Não devemos
tentar isso em máquinas de produção sem estarmos bem seguros de como
funciona internamente. Em outras palavras, estes comandos devem ser
testados antes em máquinas de desenvolvimento para adquirir
familiaridade com os danos consideráveis que podem ser causados.
O primeiro (e preocupante) exemplo de executável a ser considerado é o
próprio shell Bash. Ele não é difícil de usar, o que é muito preocupante. Já
mencionei que invadir um servidor e deixar uma forma alternativa de obter
acesso posterior é algo possibilitado pelo netcat. Com o ncat não é
necessário sequer possuir direitos root para abrir um shell. Convido o leitor
a tentar.
Em nossa máquina de escuta (Luis), cujo shell será aberto para todo
mundo, o seguinte comando deve ser executado:
Luis> # ncat --exec "/bin/bash" -l 1234 --keep-open
E para se conectar a partir do Lionel, basta executar este comando (que já
deve ser bastante familiar ao leitor neste ponto):
Lionel> # ncat Luis 1234
Na primeira conexão à porta 1234 TCP, pode ocorrer a suspeita que o shell
Bash não foi processado corretamente. Assim, tente digitar qualquer
comando Bash válido, como o de solicitar uma listagem de diretórios:
# ls
O diretório atual de Luis será mostrado, porém no console de Lionel, o que
deverá nos deixar preocupados. Digite os comandos de forma muito
cuidadosa, considerando que os retornos Bash usuais não serão mostrados,
podendo facilmente dar margem a exclusão de arquivos e execução de
comandos.
Há uma ferramenta de segurança chamada Metasploit, muito popular e
poderosa, que assume essa funcionalidade de forma mais evoluída,
tornando a backdoor persistente. Mesmo sem o Metasploit instalado para
que o leitor aprofunde seus conhecimentos, vale a pena consultar a página
a seguir, que trata do uso do netcat em máquinas Windows:
https://www.offensive-security.com/metasploit-
unleashed/persistent-netcat-backdoor/. Essa página mostra a forma
relativamente fácil de fazer alterações no registro do Windows e nas regras
do firewall seguindo as instruções fornecidas.
Seja qual for o sistema operacional em uso, o netcat disponibiliza múltiplas
opções. O leitor deve estar ciente de que, se os devidos cuidados não forem
tomados durante o teste, muitas variáveis do ambiente podem ser
disponibilizadas, causando toda sorte de problemas.
Opções diversas
Ocasionalmente, podemos sair facilmente do comportamento default, que
é usar comunicação TCP, usando as chaves -u ou --udp. Veremos mais
adiante por que isso é útil.
Da mesma forma, para iniciar o uso de SCTP (Stream Control
Transmission Protocol), o netcat pode ser provido da opção --sctp.
Outra dica útil é que também podemos acrescentar até três instâncias da
letra v, com -vvv oferecendo a maior verbosidade quando os resultados de
saída dos comandos forem mostrados.
Da mesma forma como foi utilizado para usar comandos SMTP
anteriormente, o poderoso netcat também é capaz de usar comandos
Telnet. Graças a isso, o netcat também pode ajudar caso o leitor esteja sem
acesso a um cliente Telnet. Há alguns benefícios óbvios em usar o netcat
em vez de Telnet. Para começar, o netcat é mais comedido e não entrega
dados na saída, a não ser os enviados pela máquina à qual o usuário está
conectado. Há também uns poucos caracteres de controle reservados,
significando a perda de certos dados binários se o Telnet estiver sendo
usado. Além disso, o leitor deve ter notado que o Telnet desconecta em
conexões sem atividade (idle) e interrompe o funcionamento, podendo
com isso significar o não recebimento de todos os dados de uma sessão
completa. O comando Telnet também não funciona bem com UDP, mas,
como sabemos, o netcat certamente o faz.
Resumo
Neste capítulo tratei apenas de uma parte muito pequena do potencial do
netcat; na verdade, existe simplesmente um enorme escopo a ser
explorado.
Espero que o leitor tenha assimilado os conhecimentos das funcionalidades
sofisticadas desta ferramenta, de importância crítica pela simples razão de
revelar algo mais sobre a forma como elas podem também ser utilizadas
por um invasor.
Na próxima vez que precisar mover arquivos dentro de uma LAN,
certamente usarei o netcat; é muito fácil confiar em ferramentas de
transferência de dados mais complicadas como as ferramentas SFTP para
esse tipo de tarefas simples. O comando Telnet deve ser evitado na
depuração de portas abertas e conexões; em vez disso, deve ser sempre
usado o netcat.
Em meu caso, preciso me lembrar sempre de não mostrar a certos colegas
como fazer determinadas coisas explicadas neste capítulo, visto que há
uma boa chance de eles causarem danos terríveis e deixarem grandes
brechas de segurança.
1 N. do T.: O autor não deixou explícito, mas se não informarmos uma porta específica, o número
de porta default é 31337, que pode ser lido em “leet speak” como ELEET, significando Elite.
CAPÍTULO 4
Negação de serviço
Não se pode negar que, sem certos serviços críticos operando, a internet
seria paralisada. Muitos usuários sofreriam devido à degradação de
desempenho, enquanto outros poderiam simplesmente ser sujeitos a uma
total indisponibilidade. Além do DNS (Domain Name System – Sistema de
Nomes de Domínio), o NTP (Network Time Protocol – Protocolo de
Horário da Rede) é vital para a operação bem-sucedida da internet. Neste
capítulo, dedicarei algum tempo descrevendo como os agressores podem
tentar evitar a operação correta de serviços críticos.
Infelizmente para os responsáveis por manter a internet funcionando, é
possível realizar ataques em grandes seções da infraestrutura DNS e NTP
usando diversos métodos. Por exemplo, os ataques DDoS (Distributed
Denial of Service – Negação Distribuída de Serviço) realizados no passado
eram primariamente destinados a derrubar um serviço online ou, pelo
menos, atrapalhar seus usuários de uma forma altamente frustrante,
possivelmente para obter uma vantagem competitiva ou receber um
pagamento de resgate. Atualmente, é notório que esses ataques são usados
como cortinas de fumaça para disfarçar outros ataques maliciosos.
Segundo um relatório publicado em 2014 pela Kaspersky Lab, empresas de
médio e pequeno porte teriam gasto em torno de 52 mil dólares em um
ataque DDoS. Esse valor poderia subir a cerca de 444 mil dólares para as
empresas vítimas desses ataques. Quando são considerados fatores como
perda de reputação, má vontade dos clientes no uso de serviços online
lentos (se esses serviços ainda estiverem disponíveis) e falhas nas
transações financeiras (as quais demandam envolvimento manual a ser
realizado após o evento), a proteção contra essas ameaças à infraestrutura é
uma atividade que vale a pena. O mais preocupante: das 3.900 empresas
em 27 países incluídas no levantamento originador do relatório, “mais de
um terço (38%) delas, operando no provimento de serviços financeiros ou
em serviços online públicos, foram alvo de um ataque DDoS entre abril de
2013 e maio de 2014”.
Os métodos usados para causar a negação de acesso em serviços online
críticos adquirem muitas formas. Tendo presenciado um aumento nos
ataques reflexivos (incluindo ataques de amplificação) nos últimos dois
anos, tanto em serviços NTP quanto em serviços SNMP, vou contar alguns
pontos da história por trás deles, o que está envolvido e como mitigar seus
efeitos potencialmente desastrosos.
Infraestrutura NTP
Já me referi ao fato de que os serviços críticos de infraestrutura são alvos
comuns de ataques por apresentarem um prêmio valioso para um atacante.
Como os protocolos DNS e NTP evoluíram ao longo dos anos, a segurança
foi, naturalmente, sendo incorporada aos novos releases. Vamos considerar
o NTP por um momento.
Como podemos esperar, há mecanismos de segurança inerentes dando
suporte a reforços no NTP enquanto serviço. Por exemplo, alguns
servidores NTP estrato 1 de nível superior adotam uma opção “Closed
Account”, e esses servidores não podem ser usados sem consentimento
prévio. Por outro lado, assim que é feita a adesão concordando com as
políticas de uso, os servidores OpenAccess se tornam prontamente
disponíveis para acesso. Esses servidores de acesso restrito podem, às
vezes, ter limitações de acesso devido a fatores como o número máximo de
clientes ou um intervalo mínimo de acesso, sendo ocasionalmente
disponíveis somente em determinados tipos de corporações, como as
instituições acadêmicas.
Outro componente de segurança NTP é o fato de o software cliente ser
escrito de modo a acatar as instruções geradas pelos servidores aos quais
solicita informação de tempo. Se um servidor receptor NTP assim o
preferir, ele pode simplesmente bloquear uma solicitação. De forma similar
a determinadas técnicas de roteamento e de firewall, esses pacotes são
descartados ou colocados no “buraco negro” sem qualquer intervenção.
Em outras palavras, o servidor receptor desses pacotes indesejados não
impõe uma carga extra ao sistema e apenas descarta o tráfego que pensa
não ter utilidade como resposta.
No entanto, uma resposta desse tipo nem sempre é útil, e por vezes é
melhor perguntar polidamente ao cliente se deseja suspender e desistir, em
vez de ignorar unilateralmente as solicitações. Por essa razão, existe um
tipo específico de pacote denominado Kiss-o’-Death (KoD, ou Beijo da
Morte). Caso um pacote KoD indesejado seja enviado a um cliente, este
pode aplicar àquele servidor uma marcação de negação de acesso e
procurar outra forma de atualização de horário, ou pelo menos desistir por
um período predefinido de tempo dentro dos limiares ajustados.
Há outras boas razões para cuidar da segurança geral do NTP. Além das
demandas de endereçamento IP e do impacto no uso da largura de banda
pelas operações bancárias, a infraestrutura NTP da internet deve ser
incluída na lista de serviços prestes a serem afetados pelo crescimento
exponencial e potencialmente explosivo da Internet das Coisas (Internet of
Things – IoT). Como já se sabe, bilhões de dispositivos adicionais logo
precisarão ser sincronizados, como o caso de uma geladeira poder
encomendar mais leite antes de qualquer ação do proprietário, entre outros
exemplos.
Relatórios de ataques
Quando aquele primeiro ataque NTP ocorreu, o provedor de serviços em
nuvem CloudFlare anunciou o maior ataque DDoS jamais registrado do
gênero. De acordo com a CloudFlare, o ataque chegou a quase 400 Gbit/s
de tráfego e, assustadoramente, apenas 4.529 servidores foram utilizados
para gerar toda aquela saturação de largura de banda de tráfego em 1.298
redes diferentes. Em contraste, um ataque muito divulgado que derrubou o
Spamhaus (o provedor de serviços anti-spam) usou supostamente 30.956
resolvedores DNS abertos para gerar um DDoS a 300 Gbit/s. Como
podemos ver, há uma diferença significativa de impacto quando se toma as
máquinas como base.
Outro protocolo que vem sendo usado de forma crescente em ataques
DDoS foi criado em 1988 pela PSINet, na época um dos maiores (se não o
maior) provedores de serviço internet antes de ser absorvido por diversas
fusões e aquisições.
O protocolo SNMP (Simple Network Management Protocol) está presente
na grande maioria dos dispositivos de rede, como switches e roteadores.
Esse protocolo útil possibilita que qualquer software capaz de recebê-lo
seja alimentado com informações estatísticas, como o uso da largura de
banda. O mais importante, habilitado por default, é um vetor de ataque
baseado em uma string de comunidade denominada “public”. Mesmo
quando senhas são configuradas por default, elas tendem a ser simples,
como “privado”. Isso significa que até mesmo um roteador banda larga
representa um risco potencial e pode participar de um ataque DDoS.
Considere também os dispositivos habilitados para SNMP pertencentes a
empresas ou provedores de serviço internet; pode haver dezenas de
poderosos switches e roteadores em um único segmento de rede com
acesso à largura de banda de alta capacidade. A propósito, até mesmo
impressoras em escritórios geralmente empregam implementações SNMP,
além de workstations e câmeras de vídeo IP.
Foram constatadas atividades conduzidas por atacantes fazendo
experiências com o SNMP em consideráveis ataques reflexivos/de
amplificação. As alarmantes razões de tráfego teriam atingido um valor
próximo a 1.700:1. Evidentemente, a precisão dessas estimativas ainda
precisa ser verificada, assim como o grau de alarmismo associado.
Em maio de 2014, a divisão DDoS da Akamai informou ter identificado 14
ataques SNMP. Cerca da metade deles ocorreu nos EUA, e em torno de
18% na China.
Resolvedores DNS
Quase no final de 2014, outro ataque interessante tornou-se conhecido.
Até hoje é de certa forma questionável se ele realmente pretendia ser um
ataque reflexivo, porém vou discuti-lo aqui para aumentar o conhecimento
do leitor em relação ao assunto. Como parte dos serviços oferecidos, o
Google oferece dois importantes servidores de DNS com endereços IP de
fácil memorização:
8.8.8.8
8.8.4.4
Eles permitem consultas DNS recursivas para qualquer pessoa ou
dispositivo que não tenha acesso a um servidor DNS e respondem a
qualquer consulta realizada, pelo seu cache ou por uma nova consulta caso
a resposta adequada não exista no cache. O OpenDNS oferece serviços
similares, porém filtram todas as solicitações DNS, com o objetivo de
alertar o usuário, por exemplo, caso este tenha tentado visitar um site de
phishing já anteriormente identificado. Os seus endereços IP são também
de fácil memorização, resilientes e confiáveis:
208.67.222.222
208.67.220.220
Esses serviços (geralmente) gratuitos são largamente adotados,
provavelmente por oferecerem a conveniência de não ter o overhead
associado com a execução local de servidores DNS. Entretanto, devido aos
endereços IP de fácil memorização e à excepcional confiabilidade,
infelizmente como muitos serviços populares, esses bem-intencionados
provedores apresentam outro alvo de grande valor que é atrativo para os
atacantes.
Evidentemente, há várias boas razões para prestar muita atenção aos locais
em que esses serviços são utilizados dentro da infraestrutura de produção;
a falta de controle pode torná-los comprometidos. O ataque mais óbvio,
em termos de consulta DNS, pode ser o comprometimento do cache DNS,
em que a máquina solicitante coloca uma resposta falsa e a envia a um
endereço IP ilegítimo, podendo potencialmente infectar o requisitante ou
atacá-lo de alguma outra forma. Entre os muitos ataques de
envenenamento de cache DNS estão os ataques estilo Kaminsky
(Kaminsky-style attacks; http://dankaminsky.com), que não exatamente
envenenam registros DNS individuais, mas em vez disso passam a
controlar, eles próprios, os registros da autoridade de nomes de domínio.
Há algumas informações muito bem escritas acerca dos achados do
pesquisador de segurança Dan Kaminsky em
http://unixwiz.net/techtips/iguide-kaminsky-dns-vuln.html.
Devido aos seus impactos, a relevância dos ataques DNS não deve ser
subestimada. Estima-se que os resolvedores DNS do Google atendam a
cerca de 150 bilhões de consultas por dia.
O ataque de 2014, que na superfície incluiu os endereços IP dos
resolvedores DNS do Google no último trimestre daquele ano, foi
noticiado pelos canais jornalísticos de segurança mais populares da
internet. Por exemplo, o Internet Storm Center (https://isc.sans.edu)
publicou uma matéria com dicas para identificar, no momento de sua
chegada a uma rede, os ataques supostamente vindos dos servidores de
DNS do Google. Com algumas técnicas simples de farejamento de pacotes
(packet sniffing), é possível monitorar esse tipo de ataque e verificar sua
frequência.
Neste caso, usando a ferramenta de captura de rede tcpdump, estamos
simplesmente despejando em um arquivo chamado
/tmp/suspect_traffic qualquer tráfego pertinente identificado como
suspeito. O que ocorre é a categorização daquele tráfego como qualquer
coisa recebida do endereço IP 8.8.8.8 (exatamente um dos resolvedores
DNS do Google) e destinado à porta 161.
# tcpdump -s0 -w /tmp/suspect_traffic dst port 161 and src host 8.8.8.8
Pela captura desse tráfego, pode ser feita a monitoração do seu volume e
verificar a probabilidade das solicitações DNS serem legítimas. Caso um
tráfego indesejado seja descoberto, a forma como os dispositivos afetados
se comunicam com o exterior da rede pode sofrer restrições introduzindo
regras de firewall. A ação de firewall permite que os dispositivos em
questão tenham acesso ao mundo externo.
As discussões entre os hackers do bem (white hats) e outros profissionais
da área de segurança sugeriram que esses ataques, com tráfego
aparentemente originado dos endereços IP do Google, foram na verdade
concebidos (usando os endereços IP pré-configurados como servidores
DNS dos dispositivos) para explorar e subjugar dispositivos com
configuração pobre com outras intenções nocivas, em vez de usá-los para
reflexão de tráfego. Em outras palavras, os atacantes podem
potencialmente reconfigurar esses dispositivos para seus próprios usos
desonestos em vez de negar o serviço.
Como leitura adicional, o leitor pode considerar um vetor de ataque
separado e uma tentativa de driblar os anúncios BGP legítimos (o Border
Gateway Protocol – BGP – é o protocolo de roteamento sofisticado que
integra muitas redes da internet) dos resolvedores DNS do Google; mais
informações sobre isso podem ser obtidas em
http://thehackernews.com/2014/03/google-public-dns-server-
traffic.html.
Cumplicidade
Há um conjunto de recomendações voltadas à limitação do tráfego
falsificado deixando uma rede. Infelizmente, a experiência mostra que, por
incompetência ou por falta de recursos, sempre haverá uma percentagem
de administradores de rede falhando na importância de seguir certas
diretrizes ou simplesmente não estando equipados para prestar atenção a
isso. Sem esquecer, evidentemente, a pequena percentagem desses
administradores deliberadamente deixando brechas de propósito para
atividades criminosas.
Um documento mais antigo foi escrito em 2000 para estimular debates e
dar subsídios aos interessados em manter a internet funcionando.
Chamado de Best Current Practice 38 (BPC 38;
https://tools.ietf.org/html/bcp38), este documento oferece
orientações muito bem-vindas para os administradores de rede. Ele
encoraja empresas e instituições acadêmicas, entre outras organizações, a
reforçar os diferentes aspectos das respectivas infraestruturas de rede, tanto
nos hosts quanto no equipamento de rede, para prevenir o efeito cascata na
internet.
De forma específica, ele dedica um tempo na discussão da importância da
filtragem do tráfego de entrada para proteger as redes externas de sua
própria rede, caso ela seja usada como ferramenta de ataque. Ele cita o
emprego de medidas preventivas simples, o diagnóstico e a mitigação de
um ataque vindo de uma fonte “válida” como sendo bem mais eficientes
que supor de onde vem o tráfego de origem, como foi visto na seção
anterior “Ataques reflexivos NTP”.
Diferentes níveis de filtragem do tráfego de entrada devem possibilitar a
obtenção do objetivo em diversas circunstâncias. Uma das observações
apresentadas é que, pela redução do número e da frequência dos ataques
na internet, mais recursos estarão finalmente disponíveis quando os
ataques ocorrerem. Como resultado, as respostas serão mais efetivas.
Grande parte do conteúdo presente nessas produtivas diretrizes é atribuída
ao venerável NANOG (North American Network Operators’ Group;
https://www.nanog.org), o qual, de forma veemente, discute em detalhes os
problemas das redes em uma lista de discussão por email (mailing list)
muito popular.
Mapeamento de ataques
O excelente livro Firewalls e segurança na internet: repelindo o hacker
ardiloso, escrito por William Cheswick, et al. afirma de forma sucinta na
Introdução:
A Internet é uma grande cidade, não uma série de pequenos vilarejos.
Qualquer um pode usá-la, e de forma quase anônima.
A Internet é uma vizinhança ruim.
A validade dessa citação pode ser confirmada usando a Digital Attack Map,
uma ferramenta online que proporciona uma excelente visão global dos
ataques DDoS. Com atualizações de hora em hora, ela pode ser vista em
www.digitalattackmap.com.
Totalmente gráfica, a Digital Attack Map é resultado de uma colaboração
entre a Arbor Networks e a Google Ideas, que abastecem a ferramenta com
dados enviados por cerca de 270 provedores de serviço internet em todo o
mundo. Esses provedores de serviço firmaram um acordo para
compartilhar dados com o ATLAS, sistema global de inteligência contra
ameaças da Arbor Networks. Os dados estão também disponíveis por meio
do portal de ameaças ATLAS da Arbor e pode valer a pena dar uma olhada
em www.arbornetworks.com/threats.
Além disso, em www.digitalattackmap.com/gallery, há uma galeria útil
ressaltando os ataques-chave históricos para referência. Pode ser feita uma
interação posicionando o mouse sobre os fluxos de ataque e observando
quantos gigabits por segundo extrapolaram a largura de banda durante o
ataque. São também informadas as fontes aproximadas dos ataques (por
exemplo, se um ataque foi gerado por uma botnet, ele pode ter origens em
dezenas de países diferentes), a vítima supostamente pretendida e a
duração do ataque. Há interesse também em saber as portas da fonte e do
destino usadas durante o ataque; em um dos primeiros poucos ataques aos
quais prestei consultoria, constatei a presença da porta NTP, porta UDP
123. Contudo, é interessante que as portas 80 e 53, respectivamente HTTP
e DNS, ainda parecem ser os serviços DDoS mais populares, a julgar pelos
dados disponíveis.
A Figura 4.1 contém uma amostra de ataques revelados pelo site da Digital
Attack Map, com os tipos de ataques e seus códigos de cores no lado
esquerdo do mapa global. Esta é apenas a janela inicial desse site altamente
funcional. Podemos gastar horas expandindo tanto as informações atuais
quanto as históricas permitidas pelo site em um formato facilmente
digerível.
Figura 4.1 – O abrangente site Digital Attack Map da Arbor Networks,
equipado pela Google Ideas.
Resumo
Neste capítulo, foram vistas diversas questões de segurança passíveis de
afetar os serviços críticos de infraestrutura. Esses serviços, impactados de
forma mais severa devido ao uso do UDP, mais vulnerável, ajudam de
forma genuína a operação da internet e claramente devem ser protegidos.
Alguns desses ataques são de uma concepção mais antiga, porém é
interessante notar como as categorias dos ataques reaparecem e decrescem
em diferentes períodos de tempo. Por exemplo, um ataque que não tinha
mais sido visto por muitos anos ressurge em um estado ligeiramente mais
evoluído. Como visto mais recentemente, as ferramentas de ataque SNMP
originadas da comunidade de hackers, na maioria das vezes encorajada
pelo sucesso dos ataques reflexivos NTP, geraram o maior interesse.
Mesmo não sendo possível seguir os intrincados meandros dos ataques
mais sofisticados em detalhes, a premissa é simples. Os serviços baseados
em UDP são atualmente os mais expostos a riscos. O UDP nem sempre
espera que haja respostas (o TCP conta com um handshake triplo),
portanto tem maior probabilidade de ser explorado por ataques reflexivos
e de amplificação.
O leitor pode ter pensado inicialmente que, ao bloquear inicialmente os
serviços de rede na fase da construção (apenas abrindo parcialmente os
serviços necessários usando ACLs), esses tipos de ataques raramente
poderiam impactar uma rede ou as operações diárias do sistema. No
entanto, se desejar sucesso no funcionamento de uma infraestrutura face
ao panorama de ataques atual em mutação contínua, é imperativo haver
um monitoramento permanente de como as redes e os sistemas interagem
com o mundo externo, revisando frequentemente as ACLs e as políticas.
Essa é uma proeza impossível de conseguir sem a consulta diligente às
listas de segurança e o acompanhamento vigilante dos comunicados da
imprensa técnica. Ao fazer isso, portanto, garante-se que seus serviços
internet não passarão a fazer parte do problema e a comunidade global
pode manter a internet funcionando.
CAPÍTULO 5
Nping
Funcionalidade
Na superfície, são esperadas funcionalidades relativamente limitadas do
Nping. Afinal de contas, quando um ping é emitido, uma questão é
enviada e é esperada apenas uma resposta. Embora Nping não seja ainda
uma peça de software acabada, podemos afirmar com segurança que ela é
uma ferramenta altamente abrangente e sofisticada para uso em redes.
Vamos começar nos acostumando com a sintaxe. É necessário fazer login
com privilégios de root, o superusuário, para executar alguns comandos
Nping, e nesse caso deve ser considerado o modo TCP. O primeiro
exercício é enviar “pings” TCP (o leitor leu corretamente; não são pings
ICMP) para sua máquina local. Na página de manual do ping, podemos
ver que a operação normal de ping “usa o datagrama mandatório
ECHO_REQUEST do protocolo ICMP para obter uma resposta ICMP
ECHO_RESPONSE de um host ou um gateway”. Em outras palavras, há
uma pergunta e uma resposta envolvidas.
Caso o leitor esteja se perguntando, usarei minha máquina local para esses
exemplos para evitar perturbar quaisquer outras máquinas e não
congestionar logs de firewall com atividades suspeitas. Assim como todas
as ferramentas de white hat, esta também deve ser usada com muito
cuidado.
Não apenas no caso do ICMP, a impressionante funcionalidade Nping é
uma extensão muito bem concebida do comando-padrão ping, que pode
também “falar” em muitos protocolos diferentes. Ela também possibilita
resultados de fácil compreensão.
Caso o leitor ainda não a tenha em sua máquina, a ferramenta Nping pode
ser instalada da forma descrita a seguir.
Em derivados do Debian, basta usar o comando seguinte para instalar o
pacote Nmap:
# apt-get install nmap
Em derivados do Red Hat, a instalação do Nmap é feita usando este
comando:
# yum install nmap
TCP
De volta ao exemplo do TCP (Transmission Control Protocol). O comando
a seguir pode ser rodado em uma máquina local, o que afasta a
preocupação com problemas relacionados a firewalls e não aborrece outros
administradores de sistema:
# nping -c1 --tcp -p 80,443 localhost
Nesse caso está sendo enviado para a máquina local um pacote ping (com
uma opção de contagem -c1) sobre TCP, para as portas TCP 80 e 443. A
saída desse comando pode ser parecida com a Listagem 5.1.
Listagem 5.1 – Após o envio dos primeiros pings TCP usando Nping, são dadas as boas-
vindas com um bom nível de detalhes.
Starting Nping 0.5.51 ( http://nmap.org/nping ) at 2016-11-16 11:16 GMT
SENT (0.0145s) TCP 127.0.0.1:16463 > 127.0.0.1:80 S ttl=64 id=58041
iplen=40 seq=2781160014 win=1480
RCVD (0.0148s) TCP 127.0.0.1:80 > 127.0.0.1:16463 SA ttl=64 id=0
iplen=44 seq=2400211610 win=65495 <mss 65495>
SENT (1.0148s) TCP 127.0.0.1:16463 > 127.0.0.1:433 S ttl=64 id=58041
iplen=40 seq=2781160014 win=1480
RCVD (1.0150s) TCP 127.0.0.1:433 > 127.0.0.1:16463 RA ttl=64 id=0
iplen=40 seq=0 win=0
Max rtt: 0.079ms | Min rtt: 0.055ms | Avg rtt: 0.067ms
Raw packets sent: 2 (80B) | Rcvd: 2 (84B) | Lost: 0 (0.00%)
Tx time: 1.00054s | Tx bytes/s: 79.96 | Tx pkts/s: 2.00
Rx time: 2.00171s | Rx bytes/s: 41.96 | Rx pkts/s: 1.00
Nping done: 1 IP address pinged in 2.03 seconds
A Listagem 5.1 mostra que a resposta foi obtida das duas portas TCP, a 80
e a 443. Os pings se interrompem depois de cada porta enviar dados por
uma única vez (e houver o retorno de dados) de acordo com a opção --c.
Caso não haja uma resposta válida óbvia, pode ser visto algo como
apresentado a seguir:
nping_event_handler(): READ-PCAP killed: Resource temporarily unavailable
nping_event_handler(): TIMER killed: Resource temporarily unavailable
Agora, com alguma ideia de como o Nping se parece e reage aos
comandos, não será surpresa saber que ele pode sempre usar a notação de
rede Classless Inter-Domain Routing (CIDR) (por exemplo,
10.10.10.0/24). Por enquanto, o leitor deve permanecer no básico e ter
preocupação com a forma de especificar uma faixa de portas para realizar o
ping, em vez de fazer essa especificação em uma lista recém-preparada.
Vamos considerar as “portas privilegiadas” (privileged ports) em uma
máquina Unix. No passado, alguns poucos nomes foram atribuídos a essas
portas, como portas de superusuário (superuser) ou portas de sistema, mas
essencialmente somente um usuário com privilégios de root tem permissão
para abri-las. Esta era uma funcionalidade original de segurança
significando que, em uma conexão remota a um desses números de porta,
havia uma razoável certeza de estar rodando um serviço genuíno. Em
outras palavras, a porta estaria sendo servida por um software rodando
com privilégios de root, não um usuário comum. A seguir vemos como
verificar todas as portas TCP privilegiadas com o Nping:
# nping -c1 --tcp -p 0-1024 localhost
Usando um método quase certamente diferente de outras ferramentas de
rede, o Nmap interage com múltiplos hosts e múltiplos números de porta
de forma incomum. Para manter a eficiência, caso mais de uma máquina-
alvo esteja especificada, o Nping não envia uma solicitação à primeira
máquina da lista e pacientemente espera por uma resposta. Pelo contrário,
ele emprega uma abordagem round-robin ao mesmo tempo simples e
inteligente, na qual as máquinas são contatadas de forma alternada em
uma rotação, para não introduzir retardos ao usuário quando este estiver
aguardando respostas. Com hosts múltiplos, isso é também aplicável a
múltiplas portas para dar chance de recuperação ao alvo antes de
responder à próxima porta a ser sondada pelo Nping.
Intérprete
O Nping pode funcionar como um intérprete para diversos protocolos.
Caso a opção --tcp-connect seja usada, é associado o modo de conexão
TCP para o Nping. Neste caso não é necessário usar privilégios de root
para enviar o que poderiam ser pacotes brutos (raw packets); em vez disso,
o Nping pergunta ao sistema operacional se este pode criar as conexões
apropriadas em seu nome. O conteúdo dos pacotes recebidos ou
transmitidos não pode ser visto neste modo, porém pelo menos o status
das transmissões pode ser conhecido.
Como poderíamos esperar, a opção --tcp, quando rodada pelo usuário
root, possibilita a obtenção de excelentes resultados com pacotes TCP. Por
exemplo, pode ser tentado manipular os resultados de uma conexão
completando apenas parcialmente um handshake TCP com mensagens
TCP SYN. A documentação informa que há uma possibilidade real de
ocorrer danos (na verdade, ela usa a expressão “evil” – maldade, em inglês)
com pacotes TCP RST customizados, com falsificação dos endereços IP e o
fechamento de sessões TCP ativas, portanto o leitor está devidamente
alertado.
A seguir vemos como a manipulação de handshakes TCP é apresentada no
caso de uso de três comandos separados:
# nping --tcp -p 80 --flags rst -c1 localhost
# nping --tcp -p 80 --flags syn -c1 localhost
# nping --tcp -p 80 --flags ack -c1 localhost
UDP
Podemos optar também pelo emprego de pacotes UDP (User Datagram
Protocol) usando a opção --udp. Normalmente, os pacotes TCP e UDP são
embutidos dentro de pacotes IP, porém, como já citado, sem permissões de
root, e contanto que os cabeçalhos do protocolo default não tenham sido
alterados, o conteúdo dos pacotes não pode ser visto, apenas o status da
transmissão. O mesmo é aplicável a pacotes UDP.
Um ping UDP pode às vezes descobrir máquinas onde outros protocolos
falham. É possível que um ping UDP iluda um firewall e apresente um
relatório se um dispositivo estiver escutando depois daquele firewall. Este é
um acréscimo muito útil ao kit de ferramentas. Um exemplo de comando
simples pode ser parecido com este:
# nping --udp localhost
Quando tento executar esse comando na máquina local sem ter os
privilégios de usuário de root, a seguinte mensagem de retorno é
apresentada:
SENT (0.0069s) UDP packet with 4 bytes to localhost:40125 (127.0.0.1:40125)
ERR: (0.0070s) READ to 127.0.0.1:40125 failed: Connection refused
No entanto, como superusuário, root, posso completar a transação da
seguinte maneira:
SENT (0.0161s) UDP 127.0.0.1:53 > 127.0.0.1:40125 ttl=64 id=64074 iplen=28
RCVD (0.0163s) ICMP 127.0.0.1 > 127.0.0.1 Port unreachable (type=3/code=3)
ttl=64 id=18756 iplen=56
Como podemos ver, o tráfego de ping UDP é destinado à porta UDP 40125
nos dois exemplos.
ICMP
Assim como o comando ping padrão, ao ser executado com privilégios de
usuário de root, o Nping usa o ICMP por default quando nenhum outro
protocolo estiver selecionado. A documentação afirma enfaticamente que
“qualquer tipo de mensagem ICMP pode ser criado”. Por exemplo, ao
redirecionar pacotes podemos solicitar um registro de tempo (time stamp),
gerar mensagens falsas de “destino inatingível” ou causar problemas em
outro sistema ou rede.
O leitor pode tentar o comando seguinte, logado tanto como um usuário
com privilégios de root quanto como um usuário-padrão:
# nping localhost
A diferença pode ser claramente vista pelo nível de detalhamento. A seguir
vemos o usuário-padrão, com poucos detalhes:
SENT (0.0027s) Starting TCP Handshake > localhost:80 (127.0.0.1:80)
RECV (0.0028s) Handshake with localhost:80 (127.0.0.1:80) completed
No exemplo seguinte, como usuário com privilégios de root, podemos ver
que foram fornecidas mais informações sobre o conteúdo do pacote ICMP.
O dado type=8 significa “8 Echo” de acordo com o RFC
(https://tools.ietf.org/html/rfc792), correspondendo ao esperado.
SENT (0.0152s) ICMP 127.0.0.1 > 127.0.0.1 Echo request (type=8/code=0)
ttl=64 id=31032 iplen=28
RCVD (0.0154s) ICMP 127.0.0.1 > 127.0.0.1 Echo reply (type=0/code=0)
ttl=64 id=18763 iplen=28
ARP
Há também a opção --arp, que permite experimentar o protocolo ARP
(Address Resolution Protocol – Protocolo de Resolução de Endereços).
Além de possibilitar ataques de envenenamento do cache ARP, vários tipos
de pacotes ARP podem ser criados. O agora obsoleto RARP (Reverse ARP)
era usado para a tradução de um endereço MAC em um endereço IP. O
RARP foi sucedido pelos protocolos BOOTP e DHCP, porém às vezes ele
ainda tem algum uso. Houve uma versão evoluída do RARP denominada
Dynamic RARP (DRARP), também suportada. Ela foi usada
principalmente pela Sun Microsystems próximo ao final do último milênio,
mas hoje é muito pouco usada. Há também suporte para solicitações
“InARP”, similar ao RARP, porém aplicada principalmente a redes frame
relay e ATM.
Finalmente, para complementar esses protocolos, pode ser acrescentado --
traceroute aos resultados para ajudar a determinar qual foi o caminho
tomado pelo tráfego, o que pode ser obtido consultando o endereço-fonte
dos pacotes “destino inatingível” enviados como resposta.
Opções de payload
Estando familiarizado com as opções do protocolo principal, vamos ver
como utilizar esse conhecimento recém-adquirido de forma produtiva. É
oportuno lembrar que o Nmap foi feito para atividades white hat e deve ser
usado desta forma, não para obtenção de vantagens ilegítimas.
Ferramentas dessa natureza podem causar muito tumulto.
Caso o leitor deseje acrescentar um payload (carga útil de dados) aos seus
pacotes de sondagem, há três variantes, conforme mostrado na Tabela 5.1.
Tabela 5.1 – Opções de payload e suas descrições
Opção Descrição
-- Alguns dados hexadecimais podem ser incluídos aqui. A documentação oferece exemplos
data como --data 0xdeadbeef e --data \xCA\xFE\x09
--
Uma string pode ser acrescentada, como --data-string "Per Ardua ad
data-
Astra"
string
-- Usando esta opção, um pacote com dados aleatórios entre 0 e 65.400 bytes pode ser
data- preenchido, como --data-length 999. É preciso estar ciente de que, se houver
lengthultrapassagem de 1.400 bytes, algumas MTUs na rede podem ser encobertas.
Modo Eco
Entre as sofisticadas funcionalidades incluídas no Nping está o modo Eco
(Echo mode), cuja finalidade é mostrar em detalhes o que ocorre com os
pacotes quando eles trafegam pela rede. Com a habilitação do modo Eco
em dois hosts, uma relação cliente-servidor pode ser configurada para
monitorar exatamente o comportamento durante uma troca de
informações.
Vamos dar uma olhada nesta funcionalidade. O servidor captura os
pacotes e envia os detalhes de volta para o cliente por um “canal” de
comunicações TCP. É tarefa do cliente gerar os pacotes mencionados.
Essa técnica é uma excelente forma de identificar qualquer pacote
mutilado, caso isso ocorra. E, por exemplo, caso a NAT (Network Address
Translation – Tradução de Endereços de Rede) estiver envolvida, diversos
detalhes de pacotes são também alterados. Pelo uso dessa técnica, caso um
dispositivo no sistema altere qualquer uma das opções TCP ou se houver
modelamento de tráfego, por exemplo, estes detalhes, que de outra forma
seriam de muito difícil diagnóstico, ficam aparentes. É possível também
determinar o ponto em que os pacotes em trânsito ficam misteriosamente
bloqueados, possibilitando o suporte a questões de diagnóstico.
Vamos fazer uma pequena experiência usando o modo Eco. A propósito, o
acréscimo de -vvv permite uma maior verbosidade caso deseje mais dados
na saída e um maior nível de detalhes do Nping. Para iniciar, o usuário
deve ter privilégios de root para atuar no lado servidor da conexão.
Devemos usar a senha “please_connect” (“conecte-se, por favor”) e
acrescentar verbosidade à saída recebida da interface de rede eth0 com o
seguinte comando:
# nping -e eth0 -vvv --echo-server "please_connect"
Os resultados desse comando são os seguintes:
Starting Nping 0.5.51 ( http://nmap.org/nping ) at 2016-11-16 11:16 GMT
Packet capture will be performed using network interface eth0.
Waiting for connections...
Server bound to 0.0.0.0:9929
Como podemos ver, o servidor está agora escutando um cliente em
conexão à porta TCP 9929.
Em seguida, devemos gerar algum tráfego acionando o cliente. Devemos
novamente observar que, neste caso, estamos usando no teste o localhost,
sua máquina local, tanto para o elemento servidor quanto para o elemento
cliente. Apesar de não ser a melhor forma de encaminhamento de tráfego
por um firewall ou um gateway NAT, isso oferece informações suficientes
para entender como o processo funciona.
Para rodar esse comando também é necessário ser um superusuário.
Devemos informar a senha apropriada e estar seguros de que a conexão foi
feita ao localhost. Evidentemente, esta opção pode ser substituída pelo
endereço IP da máquina remota à qual se deseja conectar da seguinte
forma:
# nping -vvv --echo-client "please_connect" localhost --tcp -p1001-1003
--flags ack
Como podemos ver, a conexão está sendo feita em três portas TCP (1001,
1002 e 1003) e em seguida aplicando nestas os pacotes TCP ACK. Se
houver dificuldades de conexão e for recebida uma mensagem de erro
“Handshake failed” (falha no handshake), a senha pode ter sido
incorretamente digitada em uma ponta.
Vamos ver o que ocorre em cada lado da conexão, começando pelo cliente.
Pelo acréscimo da opção -vvv, por um usuário com privilégios de root,
podemos ver o conteúdo dos pacotes quando estes trafegam pela rede; caso
contrário, a saída será muito mais quieta. A Listagem 5.2 mostra um
exemplo simplificado da visualização obtida.
Listagem 5.2 – Exemplo simplificado da saída de um cliente mostrando apenas um
pacote transmitido e um pacote recebido em vez de muitos pacotes
Starting Nping 0.5.51 ( http://nmap.org/nping ) at 2016-11-16 11:16 GMT
SENT (0.4256s) TCP [127.0.0.1:20869 > 127.0.0.1:1000 A seq=33133644
ack=4112791867 off=5 res=0 win=1480 csum=0x91F7 urp=0] IP [ver=4
ihl=5 tos=0x00 iplen=40 id=4058 foff=0 ttl=64 proto=6 csum=0x6cf4]
0000 45 00 00 28 0f da 00 00 40 06 6c f4 7f 00 00 01 E..(....@.l.....
0010 7f 00 00 01 51 85 03 e8 01 f9 94 4c f5 24 39 3b ....Q......L.$9;
0020 50 10 05 c8 91 f7 00 00 P.......
RCVD (0.4258s) TCP [127.0.0.1:1000 > 127.0.0.1:20869 R
seq=4112791867 ack=0 off=5 res=0 win=0 csum=0x2E11 urp=0] IP [ver=4
ihl=5 tos=0x00 iplen=40 id=0 flg=D foff=0 ttl=64 proto=6 csum=0x3cce]
0000 45 00 00 28 00 00 40 00 40 06 3c ce 7f 00 00 01 E..(..@.@.<.....
0010 7f 00 00 01 03 e8 51 85 f5 24 39 3b 00 00 00 00 ......Q..$9;....
0020 50 04 00 00 2e 11 00 00 P.......
^C
Max rtt: 0.085ms | Min rtt: 0.083ms | Avg rtt: 0.083ms
Raw packets sent: 4 (160B) | Rcvd: 4 (160B) | Lost: 0 (0.00%)| Echoed:
0 (0B)
Tx time: 3.23067s | Tx bytes/s: 49.53 | Tx pkts/s: 1.24
Rx time: 3.23067s | Rx bytes/s: 49.53 | Rx pkts/s: 1.24
Nping done: 1 IP address pinged in 3.66 seconds
Na Listagem 5.2, a saída foi resumida para a visualização de somente um
pacote “SENT” enviado pelo cliente à porta TCP 1000. Em seguida, o
cliente recebe uma resposta do servidor (recebimento, o que tem a
marcação “RCVD”) da porta TCP 1000 para a porta TCP 20869, uma das
portas efêmeras de numeração alta.
O ruído adicional, devido à opção -vvv, inclui a linha de checksum
(começando com csum) e as três linhas de conteúdo logo abaixo. O ^C
significa que a saída foi parada logo após o início, por questões de
concisão. E, assim como ocorreu com o comportamento do comando ping
padrão, são recebidos o rtt (Round Trip Times) e as estatísticas de
transmissão abaixo, seguidas de um prazo de execução geral.
No servidor (e também na máquina local, o que na realidade tem poucas
consequências), o Nping escuta na porta TCP 9929. A Listagem 5.3 mostra
a saída produzida no lado servidor.
Listagem 5.3 – Os pacotes enviados pelo cliente, vistos pela perspectiva do servidor
Starting Nping 0.5.51 ( http://nmap.org/nping ) at 2016-11-16 11:16 GMT
Packet capture will be performed using network interface eth0.
Waiting for connections...
Server bound to 0.0.0.0:9929
[1479294971] Connection received from 127.0.0.1:51099
[1479294971] Good packet specification received from client #0
(Specs=8,IP=4,Proto=6,Cnt=5)
[1479294971] NEP handshake with client #0 (127.0.0.1:51099) was
performed successfully
[1479294971] Client #0 (127.0.0.1:51099) disconnected
Na Listagem 5.3, o servidor informa “Good packet specification
received from client #0” (os pacotes recebidos do cliente #0 contêm
boas especificações) e também que um handshake foi concluído sem
qualquer problema, seguido de um instante Epoch (Epoch time stamp) do
momento da desconexão pelo cliente. Não há muito mais a coletar do lado
servidor, portanto é necessário somente fazer o login no cliente se o
servidor estiver sempre disponível para teste.
O projeto Nmap oferece de forma muito conveniente algumas máquinas de
teste para uso. A senha é “public” no caso do host “echo.nmap.org.”
Para varreduras Nmap (e não Nping), podemos tentar este host:
http://scanme.nmap.org.
Devido à grande popularidade da NAT (a conexão do leitor com a internet
provavelmente passa por pelo menos uma NAT em seu próprio roteador
doméstico), há uma boa chance de que as entradas CAPT sejam
visualizadas sob as linhas SENT e antes da próxima linha RCVD caso
aquela máquina seja solicitada. Este comando trabalha para mim:
# nping --echo-client "public" echo.nmap.org --tcp
Uma cuidadosa observação das entradas de pacotes capturados (captured
packet entries – CAPT) permite saber se a NAT alterou seu endereço da
fonte de saída. Poderemos um endereço IP privado, como o 10.10.10.10,
conforme o RFC 1918 (https://tools.ietf.org/html/rfc1918), sendo
alterado para mostrar um endereço IP roteado publicamente, como o
123.123.123.123 caso a NAT tenha sido envolvida. É relativamente fácil
detectar se a NAT está intrometida no meio da conexão. É necessário
lembrar que, onde a NAT estiver presente, por vezes poderão ocorrer
coisas como outros dispositivos alterando as MTUs (Maximum
Transmission Units – Unidades Máximas de Transmissão), mutilação de
pacotes em modelamento de tráfego, firewalls não previstos e switches
invisíveis, todos com potencial de causar mudanças sutis na conexão.
Há diversos outros cenários dentro dos quais o Nping pode auxiliar, como,
por exemplo (após algum aprendizado), ser capaz de detectar se proxies
transparentes podem ser empregados na rota. Mais adiante o leitor pode
avançar em seus conhecimentos, mas por enquanto vamos nos concentrar
na seção a seguir, que descreve algumas outras opções que podem ser úteis.
Resumo
Se o Nping for experimentado de tempos em tempos, o leitor deve enfim
perceber que o relatório por ele fornecido é realmente longo. Encorajo-o a
usar o Nmap em qualquer oportunidade.
Com suas possibilidades de criação de pacotes, o poderoso Nping pode
superar a maioria de seus rivais. O acréscimo do sofisticado modo Eco
significa que, quando temos acesso às duas pontas de uma conexão, há
menos chance de um dispositivo escapar da detecção. Como resultado, a
pesquisa de problemas pode ser feita de forma mais ágil e com menor
dificuldade.
O poderoso Nping do projeto Nmap pode ser considerado como uma
ferramenta dentro de um kit de ferramentas white hat. Usando ferramentas
desse tipo dentro da lei, o leitor se destacará nas tarefas do dia a dia e,
como uma segunda possibilidade bem-vinda, aprenderá a manter seus
servidores funcionando de forma otimizada.
CAPÍTULO 6
Análise de logs
tcpdump
Vamos dar uma olhada rápida nas opções de monitoração de pings e
traceroutes, que devem ser efetivas 24 horas por dia. Além do kit de
ferramentas útil do administrador de sistemas, devemos considerar a
poderosa ferramenta de farejamento de pacotes tcpdump. Há muito tempo
essa ferramenta tem sido utilizada para esmiuçar o tráfego de rede em
peças menores, com o objetivo de oferecer uma visão bastante
aprofundada do que está sendo transmitido.
No meu caso, por exemplo, quando desejo fazer um levantamento dos
pings ocorridos, utilizo o comando a seguir ao fazer um ping no meu
paranoico servidor a partir de outra máquina:
# /usr/sbin/tcpdump -i eth0 icmp and icmp[icmptype]=icmp-echo
No exemplo a seguir, mostrando os recursos de farejamento de pacotes
ICMP do tcpdump, os traceroutes também são detectados:
# /usr/sbin/tcpdump ip proto \\icmp
Como podemos ver no código a seguir, os pings dependem de perguntas e
respostas; no entanto, devido ao firewall paranoico do meu servidor estar
bloqueando certas partes do tráfego ICMP, um erro admin prohibited é
registrado quando os traceroutes aparecem.
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
17:06:47.925923 IP recce.chrisbinnie.tld > noid.chrisbinnie.tld: ICMP echo
request, id 21266, seq 1, length 64
17:06:47.925979 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP echo reply,
id 21266, seq 1, length 64
17:06:48.927871 IP recce.chrisbinnie.tld > noid.chrisbinnie.tld: ICMP echo
request, id 21266, seq 2, length 64
17:06:48.927921 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP echo reply,
id 21266, seq 2, length 64
17:06:49.928069 IP recce.chrisbinnie.tld > noid.chrisbinnie.tld: ICMP echo
request, id 21266, seq 3, length 64
17:06:49.928136 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP echo reply,
id 21266, seq 3, length 64
17:06:52.215139 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
17:06:52.215179 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
17:06:52.215194 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
17:06:52.215210 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
17:06:52.215220 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
17:06:52.215231 IP noid.chrisbinnie.tld > recce.chrisbinnie.tld: ICMP host
noid.chrisbinnie.tld unreachable - admin prohibited, length 68
No trecho de código, um servidor denominado noid é objeto de sondagens
de um host chamado recce. O recce está verificando se o servidor está
online.
Iptables
O comando iptables, que usa o firewall embutido no kernel do Linux,
chamado Netfilter, pode ser também empregado:
# iptables -I INPUT -p icmp --icmp-type 8 -m state --state NEW,
ESTABLISHED, RELATED -j LOG --log-level=1 --log-prefix "Pings Logged "
Se o leitor estiver prestando atenção, deve ter notado o número 8 sendo
usado como valor para --icmp-type. Na Tabela 6.1, os códigos usados
pelo ICMP podem ser vistos. Mais informações podem ser obtidas na
página RFC (Request for Comments) em
https://tools.ietf.org/html/rfc792. De acordo com essa página, o
ICMP existe desde 1981 ou por volta disso, quando a internet ainda era um
animal exótico.
Tabela 6.1 – Códigos (tipos de mensagem) do ICMP retirados do arquivo-
fonte include/linux/icmp.h, presente no kernel do Linux
Tipo Código
0 Echo Reply
3 Destination Unreachable *
4 Source Quench *
5 Redirect
8 Echo Request
B Time Exceeded *
C Parameter Problem *
D Time stamp Request
E Time stamp Reply
F Info Request
G Info Reply
H Address Mask Request
I Address Mask Reply
Como reação ao uso do ICMP em ataques, o kernel do Linux foi sendo
alterado ao longo do tempo. Devido ao uso abusivo do ICMP, as funções
marcadas com um asterisco na Tabela 6.1 são limitadas por default nas
implementações modernas do kernel (desde o Linux 2.4.10).
No trecho de código seguinte, os endereços IP de fonte e destino
(SRC=10.10.10.200 e DST=10.10.10.10) envolvidos no tráfego ping estão
logados no arquivo /var/log/messages.
Feb 31 17:19:34 noid.chrisbinnie.tld kernel: Pings Logged IN=eth0 OUT=
MAC=00:61:24:3e:1c:ef:00:30:16:3c:14:3b:02:10 SRC=10.10.10.200 DST=10.10.10.10
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=40978 SEQ=1
Feb 31 17:19:35 noid.chrisbinnie.tld kernel: Pings Logged IN=eth0 OUT=
MAC=00:61:24:3e:1c:ef:00:30:16:3c:14:3b:02:10 SRC=10.10.10.200 DST=10.10.10.10
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=40978 SEQ=2
Feb 31 17:19:36 noid.chrisbinnie.tld kernel: Pings Logged IN=eth0 OUT=
MAC=00:61:24:3e:1c:ef:00:30:16:3c:14:3b:02:10 SRC=10.10.10.200 DST=10.10.10.10
LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 CODE=0 ID=40978 SEQ=3
Se eu usasse o tcpdump ou o iptables para log do tráfego, teria muito
interesse em reduzir o tamanho dos arquivos de log. A primeira razão para
isso seria evitar que um atacante (de forma consciente ou não) causasse
problemas de espaço em disco devido à criação de pesados arquivos de log,
após a inundação de um servidor com tráfego ICMP. O segundo motivo
seria manter em valores mínimos os significativos níveis de ruído que os
logs geram, permitindo que as consultas possam ser rápidas e facilitando a
busca do que quer que estejamos querendo encontrar.
Supondo que, por questões de prudência e estabilidade do sistema, o leitor
não queira manter o tcpdump rodando em segundo plano o ano inteiro,
temos como alternativa usar o iptables para obter a informação desejada.
Vamos ver, a partir de uma visão geral mais elevada, como fazer para
eliminar o ruído de um log. Para efeitos de clareza, pode ser desejado
despejar os logs gerados pela atividade do agressor em um arquivo
separado do log do sistema (syslog).
Vou usar como exemplo o excelente rsyslog, um servidor de log do sistema
“rápido como um foguete” (mais informações podem ser encontradas em
www.rsyslog.com). O motivo dessa escolha é que o Red Hat e o Debian (e
seus muitos derivados) atualmente usam o rsyslog por default, portanto há
uma boa chance de o leitor ter acesso a ele.
Vamos dar outra olhada no exemplo de pings das iptables citado há pouco:
# iptables -I INPUT -p icmp --icmp-type 8 -m state --state NEW,
ESTABLISHED, RELATED -j LOG --log-level=1 --log-prefix "Pings Logged "
Vamos agora prestar mais atenção na opção --log-prefix, mostrada a
seguir:
--log-prefix "Pings Logged "
Caso deseje salvar todos os avisos do kernel em um novo arquivo de log,
isso é algo relativamente fácil de fazer. Abra o arquivo /etc/rsyslog.conf
e acrescente a seguinte linha na seção RULES ou próxima a ela (desde que
não exista ainda uma linha para kern.warning; caso exista, decida se deve
substituí-la ou acrescentar algo a ela):
kern.warning /var/log/iptables.log
Naturalmente, quando se trata de manipular arquivos de texto, uma
grande quantidade de resultados diferentes pode ser obtida com um script
rápido de shell (ou usando alguma ferramenta de linha de comando como
grep, awk ou sed). No entanto, com o objetivo de evitar problemas
temporários de espaço em disco, podemos tentar não fazer o log de todo
aviso do kernel no caso de uma peça de hardware começar a apresentar
comportamento indevido e registrar milhares de avisos em um curto
período de tempo.
Devemos agora criar um novo arquivo de configuração syslog e nomeá-lo
como /etc/rsyslog.d/iptables-pings-logging.conf. Esse arquivo
pode ser batizado da forma como desejar caso seu arquivo de configuração
principal (/etc/rsyslog.conf) importe o conteúdo de todos os arquivos
de configuração existentes na pasta. Por default, há uma entrada nesse
arquivo parecida com esta e que lê de uma só vez todos os arquivos de
configuração:
$IncludeConfig /etc/rsyslog.d/*.conf
No entanto, posso dizer que enfrentei problemas no funcionamento dos
filtros quando os obtive de um novo arquivo naquela pasta. Isso tudo
apesar de ter verificado as permissões e me certificado de que o syslog
remoto estava funcionando bem a partir de um dos arquivos (e tentando
startswith e regex em vez do operador contains a ser visto a seguir).
Caso o leitor se defronte com o mesmo problema, pode, em vez de
acrescentar as duas linhas seguintes ao novo arquivo de configuração em
separado, simplesmente navegar até a linha mencionando kern.* logo
abaixo de RULES no arquivo de configuração principal
(/etc/rsyslog.conf) e acrescentar estas duas linhas:
:msg, contains, "Pings" /var/log/iptables-pings.log
& ~
A primeira linha recebe entradas que incluem a string “Pings” e solicita ao
log do sistema a escrita delas no arquivo /var/log/iptables-pings.log.
A segunda linha não é muito usual e instrui o software do log do sistema a
ignorar qualquer entrada presente nas linhas anteriores para não ocorrer a
duplicação dos logs pela escrita do mesmo conteúdo em outro arquivo.
Evidentemente, é possível deixar essa segunda linha de fora se for também
desejado fazer o log em outro local.
Agora que o leitor está apto a colocar conteúdo em um arquivo de logs e
fazer a filtragem de eventos iptables específicos (acrescentando suas
próprias etiquetas se preferir), vamos ver outros exemplos.
Regras multipartes
Caso deseje que os servidores possam tanto receber pings quanto também
enviá-los, devemos levar em conta o fato de cada operação envolver
configurações de iptables ligeiramente diferentes.
A página a seguir explica como permitir pings direcionados a determinados
endereços IP do servidor (assumindo que haja mais de um IP configurado
na mesma placa de rede do servidor) junto com as diferentes configurações
de pings de saída: www.cyberciti.biz/tips/linux-iptables-9-allow-
icmp-ping.html.
Observe que o -d para destino nas regras de ping para tráfego entrante
significa um endereço IP específico.
Hardening
Se o leitor estiver preocupado com sobrecargas no sistema causadas por
tráfego ICMP, há duas coisas relativamente simples que podem ser
verificadas. Isso é possível devido ao poder dos sistemas operacionais Unix.
Em primeiro lugar (e sua máquina já deve contar com este ajuste como
default), os broadcasts ICMP podem ser ignorados pelo acréscimo da linha
seguinte na parte inferior do arquivo /etc/sysctl.conf:
net.ipv4.icmp_echo_ignore_broadcasts = 1
Esse exemplo sysctl.conf mantém a reinicialização (reboot), ao passo
que o comando a seguir fará uma ativação imediata:
# echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
O próximo comando fará ativação imediata se o exemplo sysctl.conf foi
seguido (ele recarrega todos os ajustes de configuração existentes dentro do
arquivo sysctl.conf):
# sysctl -p
O ajuste icmp_echo_ignore_broadcasts interrompe os broadcasts ICMP
para que eles não derrubem a rede com tráfego broadcast indesejado.
Na realidade, este é um ataque obsoleto (os kernels modernos usam
limitação de taxa como padrão), e o ajuste do kernel só é realmente útil
para ataques ping direcionados ao endereço broadcast que estiver forçando
todos os dispositivos no domínio de broadcast da rede local a responder.
Se cada dispositivo responder ao mesmo tempo e responder também a
outras respostas, o excesso de tráfego na rede provocará uma negação de
serviço. Todavia, assim como para todos os ajustes de kernel, é
recomendável saber mais acerca do tema para auxiliar no entendimento de
como uma rede funciona.
Outro ataque (ocorrido em 1996) foi chamado de Ping of Death (ping da
morte) e gerou números colossais de pacotes ICMP com o objetivo de
derrubar a máquina remota. Ele afetou muitas das pilhas de rede populares
(18 sistemas operacionais se revelaram vulneráveis). Bastou apenas
conhecer um endereço IP e disparar pacotes ICMP com extensão maior
que 65.536 bytes para esse endereço, e a máquina visada entrou em
colapso. O excelente site Insecure.org, em
http://insecure.org/sploits/ping-o-death.html, contém mais
informações.
Outro ataque muito comentado no passado envolveu um homem no meio
(man-in-the-middle – MITM) e foi chamado de ataque smurf. Os ataques
smurf são um bom exemplo de como a falsificação (spoofing) funciona,
pertencendo a um tipo de ataque que recentemente se tornou mais
frequente, denominado ataque de amplificação (amplification attack).
O homem no meio fica em uma posição confortável, devido à
impossibilidade de identificar a fonte original do ataque. O objetivo do
ataque é provocar a saturação da largura de banda, causando ao final uma
negação de serviço. De forma preocupante, o bloqueio do tráfego ICMP
aparece na prática como originado pelas próprias vítimas. O homem no
meio (às vezes chamado também de amplificador) recebe esses pacotes
falsificados e envia uma resposta de eco normal para a vítima, que não tem
sequer como formular uma resposta. A vítima tem possibilidades reduzidas
de interromper a chegada dos pacotes. Nos primórdios da internet, o
provedor de serviços podia somente desabilitar todo o tráfego ICMP para
interromper o fluxo massivo de dados. Devido à falsificação dos pacotes,
mesmo a realização de logs pouco ajudava no rastreio visando identificar a
origem.
Uma solução para este problema é fazer com que os próprios pacotes
tenham a taxa limitada. Isso libera a recepção do tráfego ICMP,
possibilitando à rede uma operação relativamente normal, apesar de
possivelmente um pouco mais lenta.
Isso pode ser conseguido em hardware de roteadores proprietários, como
Cisco ou Juniper, e também em hosts individuais usando iptables com um
conjunto de regras similares a estas:
# iptables -I INPUT -p icmp -m limit --limit 30/minute --limit-burst 60
-j ACCEPT
# iptables -I INPUT -p icmp -m limit --limit 6/minute --limit-burst 10
-j LOG
# iptables -I INPUT -p icmp -j DROP
Pela configuração mostrada na primeira linha, a opção --limit-burst
permite a recepção inicial de até 60 pacotes antes da habilitação da
limitação de taxa de um pacote a cada segundo (o valor 30/minuto). A
segunda linha informa que devemos determinar (embora de forma bem
mais restrita) o volume de tráfego aceito antes de fazer log no sistema: seis
entradas por minuto após uma rajada de dez pacotes. Finalmente, esses
pacotes são descartados para mitigação de qualquer efeito danoso.
Se eu estiver entendendo a documentação da forma correta, o valor --
limit-burst é referente ao período especificado usado por --limit.
Quando esse limite não é atingido, --limit-burst recebe um incremento
– em outras palavras, com o valor um – a cada vez que o limite não é
alcançado, até o número configurado.
Resumo
Algumas das alterações exploradas podem ser danosas tanto para os
sistemas quanto para as redes. O leitor deve saber o que está fazendo (o
ideal é fazer experimentos em uma máquina de teste) antes de tentar
qualquer desses ajustes em sistemas em operação. Como mencionado, o
equívoco clássico de entrar em pânico pela má reputação do ICMP e com
isso banir todas as menções a este protocolo na rede é um procedimento
imprudente.
Foram estudados os ataques e a forma de evitar que eles afetem as
operações normais da rede e dos servidores. Foi também abordada a
limitação de taxa do tráfego ICMP entrante.
Além disso, foi estudada a análise de pings e traceroutes para identificar
qualquer invasão ocorrendo com objetivos ilícitos no servidor e, mais
importante, como direcionar essas sondagens indesejadas para um arquivo
específico para que um ataque não encha os discos com volumosos
arquivos de log.
Podemos dizer com segurança: o conhecimento adquirido será raramente
necessário, porém na próxima vez que alguém alegar ter bloqueado todo o
tráfego ICMP no servidor, o leitor olhará para ele como quem conhece o
assunto e afirmará estar confiante da ausência de problemas relacionados
com ICMP.
CAPÍTULO 7
O prodigioso NSE do Nmap
Categorização de scripts
Apesar de empregar um motor subjacente altamente sofisticado, o NSE foi
cuidadosamente projetado de modo que mesmo um usuário principiante
possa entender sua operação com relativa facilidade. Portanto, é possível
usar o NSE de imediato e sem necessitar de muita leitura prévia.
No entanto, para evitar ir além das próprias possibilidades, é aconselhável
saber como o NSE se refere aos diferentes scripts que usa. Quando um
script roda no NSE, uma varredura de portas geralmente é executada antes
ou durante sua execução, para verificar o estado atual da disponibilidade
de uma máquina-alvo na rede. Há também outras similaridades entre os
diversos scripts NSE, como consultas DNS e traceroutes.
A Tabela 7.1 mostra como o NSE categoriza seus scripts; há diversas
categorias a considerar.
Tabela 7.1 – Categorias de script do NSE
Categoria Descrição
Estes scripts contemplam métodos de autenticação e a forma de contorná-los – por
auth exemplo, x11-access, ftp-anon e oracle-enum-users. A categoria
bruta é destinada à força bruta e não para autenticação.
broadcastCaso precise fazer broadcast na rede local, este pacote de scripts deve ser utilizado.
Esta coleção de scripts é usada para aplicar força bruta em credenciais de
brute autenticação em um host remoto. Há disponibilidade de muitos deles em diferentes
protocolos.
Os scripts default são executados se as opções -sC ou -A forem usadas. Para usar
default
scripts específicos, substitua o default por --script=.
Para rastrear quem e o que está conectado a uma rede, todos estes scripts são
discoveryrelacionados com exames, por exemplo, de registros públicos, dispositivos
habilitados para SNMP e serviços de diretório.
Caso deseje testar uma vulnerabilidade ou (cuidadosamente) rodar scripts que
dos tenham a possibilidade de derrubar serviços, este conjunto é adequado para as
necessidades de negação de serviço.
exploit Para testar uma exploração com o objetivo de ver se ela tem chance de sucesso.
Esteja ciente de que, pela execução destes scripts, suas ações serão registradas por
outras partes. Isso porque, em seu conjunto, estes scripts podem atuar como uma
external solicitação de terceiros, como (por exemplo) uma pesquisa WHOIS, tornando-o
assim visível para o serviço WHOIS.
Estes scripts procuram bugs de software e falha de segurança por meio de injeção de
campos aleatórios dentro das solicitações enquanto uma busca é realizada. Eles
fuzzer gastam muito mais tempo que outras técnicas para localizar um servidor offline ou
encontrar algo de interesse.
Discriminados por pertencer a uma categoria incômoda, estes scripts representam
um alto risco quando são executados, o que os afasta da categoria segura. Alguns
intrusivedesses riscos incluem panes, saturação de largura de banda e exposição a
administradores de sistema em máquinas-alvo.
Os malwares conhecidos deixam alguns rastros no sistema, como backdoors ou
malware sinais de infecção. Números de porta não usuais e excentricidades de serviço são
pesquisados com scripts de malware.
Este conjunto de scripts tem menor potencial de ofender os administradores de
safe sistemas-alvo. Ainda assim, para evitar problemas não se deve confiar
completamente neles.
Estes scripts não podem ser selecionados diretamente porque são uma extensão da
version funcionalidade de detecção da versão do NSE. Podem ser executados se a opção de
detecção de versão (-sV) for usada.
Caso sejam descobertas vulnerabilidades, este conjunto emite alertas sobre elas; por
vuln outro lado, será gerado pouco ruído. Os exemplos são realvnc-auth-bypass
e afp-path-vuln.
Fatores de contribuição
Quando o conjunto de scripts default é usado, podemos ficar surpresos
com a forma como o poderoso NSE toma suas decisões. Não há limiares
ajustados; em vez disso ele chega a um tipo de pontuação (score) depois de
rodar com base nos critérios seguintes:
• Velocidade – As varreduras default são concluídas rapidamente, por
exemplo, de modo a não empregar força bruta.
• Utilidade – Se um script não produz resultados úteis, sua inclusão em
scripts default deve ser esquecida.
• Verbosidade – A saída resultante da execução de um script deve ser
sucinta. Da mesma forma, quando não há nada a informar, o silêncio é
uma virtude.
• Confiabilidade – Inevitavelmente, premissas e suposições são feitas
durante a operação de alguns scripts. No entanto, se há erros frequentes,
elas não podem rodar na categoria default.
• Intromissão – Se um script provoca o aparecimento repentino da polícia
na sua porta, ele é provavelmente muito intrusivo para o conjunto de
scripts default.
• Privacidade – Na mesma linha do conjunto externo de scripts, os scripts
default devem respeitar a privacidade e não revelar a presença do
operador.
Falhas de segurança
Agora que o leitor já viu a multiplicidade de categorias de script do NSE e
apreciou o significado da execução do conjunto de scripts default, vamos
executar alguns testes de penetração usando os novos conhecimentos
adquiridos e a abundância de scripts empacotados como padrão no Nmap.
Vamos rodar primeiro um teste de vulnerabilidade na máquina local desta
forma:
# nmap --script vuln localhost
Na Listagem 7.3 pode ser vista a saída desse comando, observando que os
scripts de vulnerabilidade somente foram habilitados usando a opção vuln.
Listagem 7.3 – O escaneamento de vulnerabilidade direta resultou em leituras
preocupantes
Starting Nmap 5.51 ( http://nmap.org ) at 2016-11-16 11:16 GMT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00090s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
| http-enum:
|_ /icons/: Potentially interesting folder w/ directory listing
111/tcp open rpcbind
Nmap done: 1 IP address (1 host up) scanned in 1.18 seconds
Os resultados da Listagem 7.3 despertaram imediatamente meu interesse
quando vi a expressão “Potentially interesting folder” (pasta com potencial
interesse) no serviço RPC. Evidentemente, é possível que somente minha
máquina local possa interrogar a pasta /icons/ em referência, porém há
também a chance de isso ser algo a ser investigado (e de forma
relativamente urgente). Pelo firewall é possível bloquear totalmente a porta
TCP 111 ou paralisar o serviço para fazer a correção, a não ser que
estejamos cientes das regras de configuração responsáveis pela limitação do
acesso ao RPC.
Em vez de ir atrás de arquivos de configuração, meu primeiro teste para
corrigir este problema seria usar o netcat a partir de outra máquina para
interrogar a porta TCP 111 na tentativa de obter uma resposta. (O ncat
mais moderno, também escrito pelo projeto Nmap, é a minha versão
preferida ou, caso não esteja disponível, uso o comando telnet.)
Casualmente, se o NSE identificar uma vulnerabilidade conhecida, com
sorte será recebido um patch ID para servidores Windows ou algum outro
URL relevante, permitindo uma pesquisa posterior. Isso pode economizar
tempo na pesquisa de exploração online. Há uma boa chance de que, se o
NSE sinalizar de forma positiva, alguns poucos testes diferentes tenham
sido satisfeitos para chegar àquela conclusão; e, diferente de algumas
outras ferramentas, os resultados não podem ser desconsiderados sem
primeiro analisá-los.
Testes de autenticação
Vamos considerar quais seriam os resultados se mais alguém tivesse
executado o NSE do Nmap em minha máquina local, em busca de obter
autenticação. Claramente, minha máquina local tem permissões fracas (ao
falar com ela própria e não com um host remoto), porém esta forma de
teste ainda tem méritos educacionais. O comando a seguir faz exatamente
isso e procura ocorrências de script auth:
# nmap --script auth localhost
Os resultados desse comando revelam alguns dos testes executados pelo
NSE, como pode ser visto na Listagem 7.4.
Listagem 7.4 – Meus scripts de autenticação foram postos para trabalhar, novamente
em minha máquina local.
Starting Nmap 5.51 ( http://nmap.org ) at 2016-11-16 11:16 GMT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00062s latency).
Not shown: 996 closed ports
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
| http-brute:
|_ ERROR: No path was specified (see http-brute.path)
|_citrix-brute-xml: FAILED: No domain specified (use ntdomain argument)
| http-form-brute:
|_ ERROR: No uservar was specified (see http-form-brute.uservar)
| http-domino-enum-passwords:
|_ ERROR: No valid credentials were found (see domino-enum-passwords.username and
domino-enum-passwords.password)
111/tcp open rpcbind
Nmap done: 1 IP address (1 host up) scanned in 0.17 seconds
Olhando para os resultados mostrados abaixo dos números de porta na
Listagem 7.4, é possível ver que o Nmap claramente deseja mais
informações (de entradas diversas) e gerou três mensagens ERROR (erro)
nesse meio tempo. Algumas contas de usuário descobertas pelo NSE
podem ser visualizadas, dispostas sob uma seção como a “Host script
results” (resultados de script de host) ao final desta visualização caso
tenham sido obtidos nomes de usuário em função da execução da
solicitação, por exemplo, em um domínio Windows.
Descoberta
Considere o comando a seguir, para a obtenção de mais informações sobre
um host:
# nmap --script discovery localhost
Atualização de scripts
Como podemos imaginar, os scripts personalizados escritos para o NSE
usando a linguagem Lua são frequentemente melhorados e aumentados.
Caso deseje atualizar seus scripts NSE, o leitor pode fazê-lo de forma
seletiva baixando-os e copiando-os em uma pasta, de maneira similar ao
caminho mostrado a seguir, em sistemas Unix:
/usr/share/nmap/scripts
Caso haja o acréscimo ou a remoção de scripts da pasta scripts ou se a
categoria de um script foi alterada, é necessário posteriormente executar o
comando a seguir (como usuário com privilégios de root):
# nmap --script-updatedb
É esperada uma saída como esta:
Starting Nmap 5.51 ( http://nmap.org ) at 2016-11-16 11:16 GMT
NSE: Updating rule database.
NSE: Script Database updated successfully.
Nmap done: 0 IP addresses (0 hosts up) scanned in 0.14 seconds
Para baixar scripts do site Nmap, podemos clicar no link Scripts no painel
Categories em https://nmap.org/nsedoc/lib/nmap.html.
Na época da elaboração deste livro, havia cerca de 500 scripts a considerar,
cada um deles contendo informações relacionadas à sua funcionalidade.
Tipos de script
Vale mencionar que, dentro da infraestrutura subjacente do NSE, há
quatro tipos de script suportados:
• Prerule scripts (scripts pré-regra) – Como podemos imaginar, são scripts
executados na partida e antes que qualquer escaneamento seja iniciado.
Por exemplo, podemos desejar a realização de consultas DNS reversas
em uma lista de endereços IP antes de examiná-los.
• Host scripts (scripts de host) – Durante processos de escaneamento
padrão (ou seja, após descoberta, escaneamento de portas, detecção de
versão e detecção do sistema operacional), esses scripts são executados
no alvo.
• Service scripts (scripts de serviço) – Se o NSE identifica um serviço, ele
pode executar nele esses scripts. Por exemplo, há mais de 15 scripts
HTTP que podem rodar em servidores web.
• Postrule scripts (scripts pós-regra) – Rodam assim que o NSE tiver
concluído suas tarefas de escaneamento e a tendência é se concentrar na
forma como os resultados são fornecidos. Como já foi dito, a concisão é
importante, pois a verbosidade pode causar confusão.
A documentação abrangente do Nmap (encontrada em
https://nmap.org) destaca a explicação que diz: “[m]uitos scripts
podem potencialmente rodar como pré-regra ou pós-regra. Nesses casos, é
recomendável usar pré-regra por razões de consistência”.
Expressões regulares
A familiar linha de comando inteligente do NSE pode também lidar com
expressões regulares (regex). Por exemplo, mencionei os 15 scripts HTTP;
para incluir todos esses scripts em uma execução, um comando como o
mostrado a seguir deve ser executado em um servidor web alvo:
# nmap --script "http-*"
Podem também ser feitas decisões booleanas da forma mostrada a seguir
(exatamente o que seria de esperar com regex):
# nmap --script "default or safe"
Por sorte esse comando é suficientemente fácil de entender. A
documentação também apresenta este exemplo mais complexo:
# nmap --script "(default or safe or intrusive) and not http-*"
Aqui é possível ver que desejamos habilitar o default, seguro, e categorias
de script intrusivas, porém não as utilizadas em servidores web.
Zenmap
Há ocasiões, especialmente quando lidamos com muitas máquinas-alvo em
diferentes redes, que se torna necessário obter alguma ajuda com os
resultados. Imagine o leitor poder colocar os resultados em um banco de
dados, podendo assim pesquisar padrões comuns com facilidade em
escaneamentos históricos.
O Zenmap (https://nmap.org/zenmap/) representa um passo adiante. Na
qualidade de interface gráfica de usuário (Graphical User interface – GUI)
oficial do Nmap, o bem projetado Zenmap é também gratuito e apropriado
para usuários de todos os níveis. Um criador de comandos é incluído para
suporte na elaboração de comandos complexos e para possibilitar a
capacidade de pesquisar dados históricos por meio de um banco dados. É
também possível criar perfis para comandos frequentemente executados,
evitando a necessidade de redigitá-los continuamente.
Esta ferramenta gráfica multiplataforma altamente útil é disponível para
Linux, BSD, Mac OS, Windows, entre outros sistemas.
Outra funcionalidade muito bacana é poder executar um diff e depois
comparar os resultados de duas varreduras para, de forma muito fácil,
descobrir o que ocorreu entre elas.
Para usuários realizando escaneamentos frequentes, e logicamente para
qualquer usuário novato em segurança, o Zenmap é a escolha preferencial.
Os usuários de todos os níveis de experiência descobrem que a curva de
aprendizado é consideravelmente menos traumática se o Zenmap for usado
primeiro. A Figura 7.1 mostra o que pode ser esperado com o uso do
Zenmap gráfico em um Desktop Manager no Linux.
Resumo
Neste capítulo foram abordados alguns aspectos da funcionalidade básica
do Nmap, introduzidas e explicadas as diferentes categorias de script do
NSE, discutidos os tipos de scripts usados pelo Nmap e explorados os usos
de uma interface gráfica de usuário para afastar a complexidade inicial de
tarefas repetitivas. Naturalmente, não posso deixar de mencionar outra vez
que a interface gráfica de usuário também auxilia em análises.
Para começar
Antes de começar a avaliação do LMD em si, vamos considerar alguns
aspectos potencialmente menos óbvios do que é necessário para manter
qualquer software anti-malware funcionando corretamente e com sucesso.
Frequência de atualização das definições
É fundamental que as atualizações de assinaturas de malware sejam
realizadas frequentemente; de fato, o seu sistema pode ficar vulnerável caso
a última atualização não tenha sido feita. A arquitetura intrínseca do
software de detecção é de pouca valia se as ameaças mais recentes não
forem detectadas. Felizmente, o LMD frequentemente providencia ele
próprio suas atualizações, das quais gera assinaturas de dados
comunitários, submissões de usuários e dados de firewall sobre ameaças
ativas de malware.
O site LMD oferece um feed RSS das últimas ameaças, oferecendo também
uma versão paga, outro incentivo para que as atualizações sejam atuais e
relevantes. O feed, repleto de achados de malware correntes coletados pelo
LMD, pode ser encontrado em https://www.rfxn.com/feed/.
O site do LMD afirma que as assinaturas recebem uma atualização
praticamente diária, ou com uma frequência maior caso uma intensa
atividade seja constatada.
Ameaças prevalentes
Quando este livro estava sendo escrito, o LMD alegava manter 10.822
assinaturas de malware em seu banco de dados. Olhando para o conteúdo
da Figura 8.1, podemos ver uma lista das 60 ameaças mais prevalentes
contidas no banco de dados do LMD. Como esperado, a linguagem de
script no lado servidor mais popular em todo o mundo, a PHP
(https://www.php.net), é um vetor de ataque comum. A poderosa
linguagem Perl também aparece com destaque.
Funcionalidades LMD
O conjunto de funcionalidades do LMD está longe de ser trivial. Na Figura
8.2 podem ser vistas as funcionalidades relacionadas em sua
documentação.
Figura 8.1 – Os 60 ataques mais prevalentes de acordo com o LMD.
Figura 8.2 – A considerável lista de funcionalidades oferecidas pelo LMD.
É possível dizer que, além da detecção inteligente de ameaças, o LMD atua
na combinação de relatórios abrangentes com a colocação das ameaças em
quarentena, entre diversas outras funcionalidades. A facilidade em receber
relatórios resumidos diariamente via email por meio de uma tarefa cron é
claramente útil para transmitir segurança em relação ao funcionamento do
sistema de detecção conforme o esperado. Adicionalmente, a capacidade
do LMD em se conectar ao Apache e monitorar diretamente os uploads de
arquivos dos usuários será abordada mais adiante. Caso esta seja a única
forma usada pelo usuário para obter arquivos em um sistema, ela é
claramente uma escolha à prova de balas.
Instalação
Vamos ver agora a instalação do LMD, tanto em derivados do Debian
quanto Red Hat. Primeiro, devemos verificar se o pacote wget está
instalado. No caso do Red Hat é o seguinte comando:
# yum install wget
A alternativa para o Debian é:
# apt-get install wget
Muitas distribuições incluem o wget por default, portanto isso talvez não
seja necessário.
Para obter o máximo do LMD, também podemos instalar o inotify-
tools caso desejemos que o LMD realize interface direta com o inotify.
Mais informações e o download do inotify-tools podem ser obtidos de
https://github.com/rvoicilas/inotify-tools/wiki.
No entanto, para fazer esta instalação a partir do seu gerenciador de
pacotes, caso tenha sorte e use um “filho” do Red Hat, o leitor pode usar
este comando:
# yum install inotify-tools
E, em máquinas da linhagem Debian, o comando a executar é:
# apt-get install inotify-tools
Se isso não funcionar em seu sabor Debian, tente o procedimento a seguir.
Sei que isso funciona porque quis comprovar a facilidade de instalação do
LMD no Ubuntu 14.04 LTS. Precisei acrescentar o repositório Universe
para ter sucesso na instalação do pacote inotify-tools em meu arquivo
/etc/apt/sources.list, como segue:
deb http://us.archive.ubuntu.com/ubuntu trusty main universe
A palavra “trusty” pode ser mudada para “precise” ou outro nome de
versão do Ubuntu caso esteja usando outros sabores. As listas de pacotes
podem ser então atualizadas com o seguinte comando:
# apt-get update
O comando Ubuntu final pode ser simplesmente como este:
# apt-get install inotify-tools
Vou deixar para o leitor experimentar igualmente com repositórios Debian
(substituindo “trusty” pelo nome da versão apropriada no Debian).
Como o pacote LMD não estava disponível em nenhum repositório na
época da elaboração deste livro, ele pode ser baixado e instalado da
seguinte forma:
# cd /usr/local/src/
# wget http://www.rfxn.com/downloads/maldetect-current.tar.gz
# tar -xzf maldetect-current.tar.gz
# cd maldetect-*
# sh ./install.sh
Após rodar o script install.sh, como mostrado na última linha de
comando, será apresentada uma tela com um conteúdo que inclui o
seguinte:
Linux Malware Detect v1.5
(C) 2002-2015, R-fx Networks <proj@r-fx.org>
(C) 2015, Ryan MacDonald <ryan@r-fx.org>
This program may be freely redistributed under the terms of the GNU GPL
installation completed to /usr/local/maldetect
config file: /usr/local/maldetect/conf.maldet
exec file: /usr/local/maldetect/maldet
exec link: /usr/local/sbin/maldet
exec link: /usr/local/sbin/lmd
cron.daily: /etc/cron.daily/maldet
maldet(6617): {sigup} performing signature update check...
maldet(6617): {sigup} local signature set is version 2015112028602
maldet(6617): {sigup} latest signature set already installed
Os caminhos de instalação escolhidos certamente podem sofrer variações
caso o script install.sh tenha sido editado (a variável inspath em
particular). Como podemos ver, também é incluída uma nota informando
o status da atualização das assinaturas LMD.
Modos de monitoração
Com o pacote já instalado, vamos ver o que o LMD pode monitorar em um
sistema. Uma boa forma de começar é considerar os modos de
monitoração do LMD.
O LMD oferece diversos modos de monitoração que podem ser
configurados para verificar diferentes partes de um sistema de arquivos.
Como será visto, o LMD usa o executável binário denominado Maldet,
forma abreviada de “malware detect” (detecção de malwares).
Para monitorar um componente do sistema, pode ser usada a opção -m,
também grafada como --monitor. O que o LMD pode monitorar pode ser
decomposto entre usuários, arquivos e caminhos. O site apresenta o
exemplo seguinte de como os três modos podem aparecer na linha de
comando:
# maldet --monitor users
# maldet --monitor /root/monitor_paths
# maldet --monitor /home/mike,/home/ashton
Pelo uso da primeira opção, --monitor users, o LMD faz a monitoração
de qualquer identificador único (unique identifier – UID) no sistema que
estiver acima de um ajuste UID mínimo (a opção de configuração a ser
ajustada no arquivo de configuração é chamada de notify_minuid).
O segundo exemplo é um arquivo, /root/monitor_paths, que pode
conter os arquivos cuja monitoração é desejada (um item por linha).
No caso da terceira opção, poderíamos criar uma única linha de comando
extensa, com uma lista de caminhos de sistema de arquivos separados por
vírgula dos itens que queremos monitorar.
A Figura 8.3 mostra o resultado da execução do seguinte comando:
# maldet -m /home/ubuntu
Configuração
O arquivo de configuração principal do LMD é
/usr/local/maldetect/conf.maldet. Ele é bem comentado e muito útil
para compreender como o LMD prefere ser ajustado.
Todavia, um alerta antes de continuar: o arquivo de configuração do LMD
não usa asterisco como caractere curinga, mas sim um ponto de
interrogação. Portanto, o caractere ? pode ser usado no lugar de * para
substituir caracteres múltiplos em uma opção de configuração. Apesar
dessa pequena ressalva, o uso é relativamente simples.
Exclusões
Vamos ver como fazer os ajustes no LMD. A documentação começa
perguntando ao usuário quais elementos do sistema ele deseja ignorar. No
mesmo estilo adotado para os modos de monitoração recém-estudados, há
arquivos que podem ser preenchidos com dados para conseguir isso. Cada
entrada nos arquivos de configuração a seguir deve estar contida em sua
própria linha.
No arquivo seguinte podemos acrescentar caminhos completos de arquivos
que não desejamos que o LMD verifique:
/usr/local/maldetect/ignore_paths.
Podemos também excluir globalmente uma extensão de arquivo específica
colocando uma entrada do tipo .jpg neste arquivo:
/usr/local/maldetect/ignore_file_ext.
Por uma razão ou outra, certas assinaturas LMD podem levar a linhas
desnecessárias e de pouca utilidade nos arquivos de log. Determinadas
assinaturas podem ser desabilitadas pelo acréscimo de uma linha do tipo
php.mailer.10hack a este arquivo:
/usr/local/maldetect/ignore_sigs.
A última opção de exclusão significa que podem ser usadas expressões
regulares (regex) sofisticadas para compatibilizar de uma só vez múltiplos
caminhos do sistema de arquivos. Basta acrescentar uma lista ao arquivo
/usr/local/maldetect/ignore_inotify, que usa um formato como:
^/home/premium-user-$
Evidentemente, com o uso de regex, as possibilidades de compatibilização
de arquivos são inúmeras, podendo ser usadas para evitar a realização de
alterações manuais na configuração no caso de um novo usuário receber
permissão para se logar no servidor. Esse exemplo de regex ressalta que um
conjunto específico de usuários pode receber um nome, com o formato de
nome de usuário nas linhas premium-user-123456.
Relatórios
Vamos fazer uma verificação rápida na forma como o LMD gera seus
relatórios. A Figura 8.4 mostra um relatório produzido.
Quarentena e limpeza
A documentação ressalta que o LMD, por default, não atua quando
encontra arquivos suspeitos (evil-look files). Portanto, é importante
entender que, na maioria dos casos, o malware deve ser posto em
quarentena manualmente.
Caso esteja certo de que deseja habilitar a quarentena automática, isso
pode ser feito ajustando a opção de configuração quar_hits=1 no arquivo
de configuração principal, residente por default em
/usr/local/maldetect/conf.maldet.
Caso deseje colocar em quarentena todos os malwares obtidos em uma
varredura específica, devemos usar a opção -q, que é igual a --quarantine
SCANID:
# maldet -q 010116-1111.21212
Caso tenha havido um engano, os arquivos em quarentena podem ser
recuperados de um SCANID específico usando o comando a seguir, que é
igual ao da função --restore:
# maldet -s 010116-1111.21212
Um erro como o mostrado a seguir é visualizado caso nada exista a
recuperar:
maldet(18748): {restore} could not find a valid hit list to restore.
Se desejar que o LMD tente corrigir as infecções por malware por ele
descobertas, o comando a ser usado é o --clean, também grafado como
opção -n. A seguir é mostrado um exemplo de comando para limpeza de
malware encontrado em um SCANID em particular:
# maldet -n 010116-1111.21212
Para uma limpeza ser considerada bem-sucedida, a varredura resultante
após a limpeza de uma infecção de malware deve ocorrer sem que haja
registro de HIT de um arquivo problemático.
Caso haja dúvidas em relação aos resultados ou não estiver seguro de que
as alterações de configuração funcionaram da forma correta, pode ser feita
uma purga de todos os dados de sessão, logs e arquivos temporários
existentes usando o seguinte comando:
# maldet -p
O resultado deve ser similar a:
maldet(19219): {glob} logs and quarantine data cleared by user request (-p)
Atualização do LMD
Como disse no começo deste capítulo, a atualização das assinaturas LMD é
de importância primordial. Para fazer manualmente uma atualização,
devemos usar a opção de comando -u. Caso o leitor esteja se perguntando,
saiba que ao fazer isso é feita conexão ao site rfxn.com para baixar os
dados. Pode ser feita tentativa manual com -u, ou seu equivalente --
update, desta forma:
# maldet -u
Os resultados esperados devem ser parecidos com:
maldet(19278): {sigup} performing signature update check...
maldet(19278): {sigup} local signature set is version 2015112028602
maldet(19278): {sigup} latest signature set already installed
Há também um mecanismo inteligente para a atualização da versão
atualmente instalada, também via rfxn.com:
# maldet --update-ver
Isso pode ser abreviado para -d caso deseje, e os resultados desse comando
serão parecidos com:
maldet(19357): {update} checking for available updates...
maldet(19357): {update} hashing install files and checking against server...
maldet(19357): {update} latest version already installed.
Execução e parada de varreduras
Na Figura 8.1 foram vistos os resultados da monitoração de um caminho
em particular com a opção -m ou --monitor. Vamos dedicar um tempo a
isso visando um melhor entendimento.
Imagine que seja desejado monitorar duas partições de sistema de arquivos
em particular, devido aos usuários terem a capacidade potencial de
escrever dados nelas. A monitoração dos caminhos pode ser feita da
seguinte forma:
# maldet -m /usr/local,/home
Observe a vírgula separando os caminhos. A saída para rodar esse
comando é mostrada na Figura 8.5. Devemos lembrar que varreduras
extensas podem usar a opção background -b, como visto anteriormente.
Tarefa cron
O LMD inclui uma funcionalidade de tarefa cron (cron job) diária,
localizada em /etc/cron.daily/maldet. Ela atualiza as assinaturas e
limpa os dados de varredura, mantendo essas informações por até quatorze
dias, rodando também uma varredura diária usando a configuração
especificada.
Observe que os dados de sessão e os arquivos temporários são mantidos
entre as execuções de tarefa cron. Como resultado, é necessário executar a
opção -p anteriormente mencionada para purgar esses arquivos caso
suspeitemos da exatidão dos resultados.
Os parâmetros de configuração de email devem ser ajustados para
possibilitar o recebimento de relatórios diários a cada manhã. A
atualização diária é importante por razões de arquivamento dos emails e
para garantir que as varreduras possam ocorrer diariamente e não sejam
sujeitas a falhas.
Relatórios de malware
O grau de sofisticação e a concepção aprimorada do LMD são
funcionalidades bem conhecidas, portanto não é surpresa que o LMD
contenha um mecanismo simples para gravar arquivos suspeitos para
análise. No caso de arquivos evidenciando conter alguma variedade
desconhecida de malware, novas assinaturas podem ser criadas e
acrescentadas à lista de ameaças conhecidas do LMD, visando a divulgação
desse malware para outros usuários. O método usado para enviar arquivos
de volta ao LMD para verificação é mostrado a seguir, usando a
funcionalidade --checkout, também grafada com a opção -c:
# maldet -c suspicious_file.gz
Quando esse comando é executado, o arquivo é enviado para rfxn.com e
analisado em um momento oportuno.
Resumo
Além de tratar do LMD, abordei o mecanismo inotify que ele usa para
verificar as alterações no sistema de arquivos. O inteligente e eficiente
inotify realiza verificações de malwares em tempo real sem introduzir
cargas significativas no sistema.
Com os smartphones Android atualmente respondendo por cerca de 80%
do mercado global, não há muitas dúvidas de que os malwares produzidos
para explorar vulnerabilidades nesses dispositivos deverão futuramente
afetar também em alto grau os dispositivos de usuários Linux, o mesmo
ocorrendo com os servidores.
Com a adoção de testes de sistema de arquivos em tempo real pelo uso de
ferramentas sofisticadas como o LMD, os riscos de infecções por malwares
devem ser significativamente reduzidos. O LMD foi inicialmente concebido
para atender servidores de hospedagem compartilhada porque seu criador
levou em conta um vetor de ataque que normalmente é ignorado por
outros produtos: a conta de usuário. Geralmente, os produtos de detecção
de malware do mercado focam infecções de kernel e rootkit.
Supondo que o leitor instalou primeiro o LMD em um ambiente de testes e
se familiarizou com a forma como ele opera, entendo que definitivamente
vale a pena usar o LMD em máquinas em produção.
CAPÍTULO 9
Quebra de senhas com Hashcat
História
Outra ferramenta de segurança popular e venerável usada para ripar senhas
é chamada de John the Ripper, de origem um tanto antiga. A Hashcat
entrou em cena em 2009, tomando a iniciativa de usar CPU multitarefa
para realizar quebra de senhas. À época, apesar de outros desenvolvedores
de ferramentas terem começado a considerar o uso de todos os núcleos
disponíveis de uma CPU, nenhum deles foi capaz de fazer isso de forma
plena e sem patchings (correções). Durante o desenvolvimento da Hashcat,
percebeu-se que fazia todo sentido tirar vantagens da capacidade das
modernas CPUs e com isso agilizar significativamente o processo de
recuperação de senhas.
Para evitar confusão: a Hashcat originalmente passou por alguns nomes
diferentes em seus primeiros releases, como atomcrack e Dr. Hash. A partir
da versão 0.30, o nome Hashcat, pelo qual é agora conhecida, foi aplicado
ao software (e tenho certeza de que conhecendo-a melhor, o leitor vai
começar a amar essa ferramenta).
Keyspace
É importante compreender o conceito do que é o keyspace em criptografia.
O termo tem certa relação com a quantidade de esforços despendidos por
uma ferramenta de quebra de senhas.
O keyspace é basicamente o conjunto de teclas disponíveis usadas na
geração de uma determinada chave. O NIST (National Institute of
Standards and Technology – Instituto Nacional de Normas e Tecnologia)
descreve keyspace como “o número total de valores possíveis que uma
chave, como uma senha, por exemplo, pode conter”.
Ele continua: “Um componente de keyspace usado em senhas comuns é o
conjunto de caracteres (Character Set) usado para formar a chave”.
Em outras palavras, em uma senha podem ser usados somente os
caracteres existentes no teclado (ou o conjunto de caracteres encontrados
localmente em uma determinada aplicação), sendo que eles representam o
keyspace da senha.
Até mesmo um caractere único pode ter um keyspace de dez caracteres se
ele for um número, indo de zero a nove.
A segurança de uma senha pode ser aprimorada aumentando tanto o seu
comprimento quanto o tamanho do conjunto de caracteres. Assim, por
exemplo, uma senha com 16 caracteres que usa um conjunto de caracteres
com tamanho de 10 caracteres tem um keyspace de
10.000.000.000.000.000, tornando-a muito mais difícil de atacar quando
comparado com o keyspace de 10 caracteres de um único caractere.
Este site útil pode encorajar o leitor a aumentar a segurança de suas senhas:
https://howsecureismypassword.net.
Esse site, ao mesmo tempo simples e sofisticado, usa termos básicos e
discute as possíveis combinações levando em conta o keyspace. Após
informar a senha, um clique no link SHOW DETAILS (Mostrar detalhes)
sob a caixa de entrada1 faz o site mostrar o nível de segurança dessa senha.
Por exemplo, a tela apresentou as seguintes informações depois que
informei uma senha de somente um caractere:
Length 1 characters
Character Combinations 10
Calculations Per Second 4 billion
Possible Combinations 10
Vamos agora para uma parte muito preocupante para o leitor. A poderosa
ferramenta de senhas do site “How Secure Is My Password” (Quão segura é
minha senha) informa que o tempo necessário para quebrar a senha do
dígito por mim informado é de aproximadamente 0,0000000025 segundos
em um computador desktop convencional. Imagine então a rapidez disso
quando estiver sendo usada a capacidade de processamento resultante do
uso combinado de muitas placas de vídeo.
Por outro lado, tentando ser um pouco mais inteligente, vamos ver o que
acontece no exemplo seguinte quando é usada uma senha de 16 caracteres.
Casualmente, estou usando o conjunto de caracteres default do meu
computador, portanto neste caso o conjunto com 10 caracteres de
comprimento citado não é aplicável.
A senha digitada foi uma combinação de caracteres alfabéticos maiúsculos
e minúsculos, números e caracteres especiais, mostrada a seguir:
Rx951&RTdIp-"2YT
Nesse caso o site respondeu com um tempo mais reconfortante para
conseguir a quebra: 412 trilhões de anos. Como podemos ver na tela
seguinte, alguns novos vocábulos foram incluídos (for me – para mim; at
least – pelo menos). Aparentemente, a palavra “nonillion” (nonilhão) é um
número seguido de 30 zeros nos Estados Unidos e de 54 zeros no Reino
Unido.
Length 16 characters
Character Combinations 96
Calculations Per Second 4 billion
Possible Combinations 52 nonillion
Desse exemplo, podemos depreender claramente que uma senha
“complicada” padrão com comprimento de oito caracteres é preferida em
vez de usar uma senha única de um caractere.
Hashes
Agora que foi mostrado como uma senha complexa pode aumentar
drasticamente o esforço envolvido em um ataque, vou continuar minha
explanação sobre quebra de senhas. No entanto, é necessário primeiro uma
última explicação.
Como o nome sugere, a Hashcat lida com hashes de senha. A criação de
um hash em criptografia envolve a conversão de uma string de caracteres,
como uma senha, em um número determinado de caracteres, resultando
em algo análogo a uma impressão digital. Não há como desfazer ou
reverter um hash (bem, é possível fazê-lo na prática, porém é muito, muito
difícil).
Aqui estão dois exemplos MD5. Primeiro, o hash para a palavra “hello” é:
5d41402abc4b2a76b9719d911017c592
Segundo, o hash MD5 para “Hello” com inicial maiúscula é:
8b1a9953c4611296a827abf8c47804d7
Como podemos ver, a mudança de um único caractere de minúsculo para
maiúsculo fez uma enorme diferença.
Agora, se usarmos outra palavra, “Hello There,” fica assim:
32b170d923b654360f351267bf440045
O hash MD5 de duas palavras tem o mesmo comprimento do exemplo
anterior, com uma única palavra. Sabendo que seus hashes têm sempre o
mesmo comprimento, é possível dizer se uma string de caracteres
aparentemente não relacionados atende a um padrão.
Da mesma forma, pense por um segundo sobre por que não
criptografamos senhas em um servidor Linux e depois descriptografamos o
arquivo de senhas do sistema quando um usuário faz login. A resposta é:
simplesmente porque o processo de criptografar dados pode ser revertido,
enquanto uma função de mão única (one-way function) é preferível
quando comparada com a criptografia de uma senha. Algumas pessoas
ficam surpresas ao saber que o arquivo /etc/shadow efetivamente não
lembra uma senha de usuário, apenas de uma versão de hash temperado
(salted hash) dela.
Por que uma entrada no arquivo de senhas /etc/shadow do Linux é
apresentada desta forma? À primeira vista, ela se parece com alguma forma
de criptografia.
chrisbinnie:$6$TRIYWb5l$ef6Tm54qpV2nYCn6f20b7w/
5nvp8zpsjacFqeTwqx7fCeW3plG2pkKsGgf1CtWzWhHOPWykFGrfPGmCde4HWY/
:12231:3:32:11:32::
O usuário chrisbinnie tem uma entrada muito extensa porque a Shadow
Suite está usando um salt para reforço posterior das senhas. Depois de um
usuário introduzir uma senha em um sistema Linux, por default, um salt é
usado.
No pacote de criptografia do Linux, por exemplo, salt é uma string de dois
caracteres escolhida de um conjunto de caracteres. Pode ser qualquer um
deles no conjunto de caracteres da língua inglesa (a-z, A-Z, 0-9./). Tendo
escolhido um tempero, o algoritmo original usado para o hash da senha de
usuário é então “perturbado” de 4.096 formas diferentes. O tempero é
então salvo na senha codificada.
Por um momento, vamos pensar um pouco mais sobre senhas Linux. Os
modernos sistemas Linux aumentam a segurança de suas senhas com
senhas Shadow. Antes, as senhas eram armazenadas no arquivo
/etc/passwd, que podia ser lido por todos os usuários de um sistema. No
entanto, somente o root pode ler o arquivo /etc/shadow, e isso torna
possível a aplicação adequada de outras políticas, como o envelhecimento
de senhas.
O processo de login de usuário funciona desta forma. Quando alguém se
loga em uma máquina, o salt da entrada relevante desse usuário no arquivo
/etc/shadow é lido. Em seguida, a senha digitada pelo usuário é codificada
com o tempero que acabou de ser lido. Os resultados desse processo são
checados em relação à senha salva em /etc/shadow. Caso elas sejam
idênticas, o acesso é permitido ao usuário. Simples e inteligente2.
Uma forma comum de ataque a uma lista de senhas é o conhecimento
antecipado dos hashes de um conjunto de senhas corriqueiras e a
combinação destas com os 4.096 valores de salt disponíveis. Isso é
conhecido como ataque de dicionário.
Já foi citado que, hoje em dia, o mínimo estritamente necessário para a
especificação de um sistema de senhas seguras deve incluir um algoritmo
hashing atualizado, e o hash resultante deve ser temperado. Os populares
algoritmos modernos de hashing incluem SHA256, SHA512, whirlpool,
tiger, ripemd e SHA3. Cada um deles apresenta sutis diferenças em seus
atributos.
Esses algoritmos não devem ser confundidos com os algoritmos
criptográficos como os 3DES, Triple DES, Crypt, Blowfish e Rijndael.
Uso da Hashcat
A Hashcat, flexível e bem projetada, inclui uma extensa lista de hashes e
wordlists para experimentações. Vamos ver como trabalhar com tudo isso.
Capacidades da Hashcat
A abordagem geral das ferramentas de quebra de senhas (password-
cracking tools) consiste em importar um arquivo de senhas cheio de dados
criptografados e em seguida gerar um arquivo de saída resultante do
processamento do arquivo de entrada. Vamos ver algumas das opções
disponíveis na ferramenta Hashcat. As outras ferramentas disponíveis na
suíte de software serão abordadas em um momento oportuno.
A Hashcat suporta diversos tipos de algoritmos de hashing, como MD5,
SHA1 e NTLM. Na realidade, se meus cálculos estiverem corretos, o
número ultrapassa inacreditáveis 90 variedades. A Hashcat alega que pode
quebrar as versões MD5 de aplicativos populares como o WordPress,
Cisco-ASA e Drupal 7. Além do seu impressionante suporte a algoritmos,
os muitos e diferentes modos de ataque disponíveis incluem força bruta,
ataques de dicionário, ataques baseados em regras (rule-based) e ataques
de impressão digital (fingerprint).
Instalação
Quando este livro estava sendo escrito, a versão da Hashcat era a v2.003.
Para instalar a Hashcat (supondo não encontrá-la nos repositórios das
distribuições), o leitor pode ir para o site e baixar os últimos binários. O
link direto para a v2.00 é este: https://hashcat.net/files/hashcat-
2.00.7z.
O link para a versão 2.00 está no alto da página em
https://hashcat.net/hashcat/. Nessa página, deve ser feita uma
verificação para assegurarmos que a última versão disponível está sendo
baixada.
Após o download, é necessário somente extrair o arquivo .7z e assegurar-
se de possuir a permissão correta para escrever arquivos no diretório do
qual os arquivos foram extraídos. Caso tenha havido problemas durante a
extração de qualquer derivativo Debian, o pacote 7za pode ser então
instalado usando o seguinte comando:
# apt-get install p7zip-full
Em derivados do Red Hat, pode ser necessário adicionar um repositório.
Feito isso, o comando a seguir deverá trabalhar para você:
# yum install p7zip p7zip-plugins
Em seguida, para extrair os arquivos compactados e preservar os nomes de
diretório com x, rode o arquivo 7za com:
# 7za x hashcat-2.00.7z
Observe a falta do sinal de menos antes do x, o que corresponde à
convenção usual. Isso não é um erro de digitação.
Tendo feito isso, podemos agora usar cd no diretório hashcat-2.00/
recém-criado, o qual contém muitos arquivos e subdiretórios. Os diretórios
docs e examples são de particular interesse, que o leitor pode explorar à
vontade. Não se preocupe, pois daqui a pouco será explicado como rodar o
executável Hashcat.
A propósito, caso o leitor esteja interessado na última versão de
desenvolvimento, pode acessar a página GitHub em
https://github.com/hashcat/hashcat. Ela inclui também
documentação e links para o wiki, o que pode ser interessante.
Se o leitor estiver rodando a sofisticada suíte de testes de penetração Kali
Linux, está habilitado a instalar a Hashcat da maneira mostrada a seguir,
graças ao fato de ela estar incluída:
# apt-get install hashcat
Tabelas rainbow
Em vez de se apoiar na capacidade de uma CPU ou uma GPU do sistema,
outra abordagem é fazer isso em seu armazenamento, usando
potencialmente centenas ou milhares de gigabytes. Durante um ataque de
força bruta, em vez de calcular um hash a cada tentativa, é possível
consultar tabelas com respostas pré-calculadas existentes em uma extensa
lista. São as tabelas rainbow (rainbow tables).
Há formas de frustrar essa abordagem, notadamente usando grandes sais
em hashes unidirecionais (one-way hashes). Isso funciona muito bem
porque cada senha recebe um hash com um salt único, portanto cada
possível hash calculado do salt deve necessitar de uma entrada em uma
tabela rainbow em conjunto com o seu salt.
Execução da Hashcat
Agora que temos algum conhecimento sobre hashes, modos de ataque e de
onde baixar uma wordlist (e considerando a dedicação do leitor ao grande
número de exemplos informativos, é possível atestar a utilidade deste
conhecimento), finalmente é possível rodar a Hashcat.
O conteúdo do meu diretório de instalação é o seguinte:
charsets/ hashcat-cli32.exe hashcat-cliXOP.bin tables/ hashcat
-cli64.app hashcat-cliXOP.exe
docs/ hashcat-cli64.bin rules/ hashcat-cli32.bin examples/
hashcat-cli64.exe salts/
Na minha lista de diretórios é possível ver que há diversos tipos de
executáveis.
Para as finalidades do leitor, qualquer coisa que termine com .bin deve ser
suficiente. Se por alguma razão os arquivos .bin não estiverem na
condição executável de imediato, usualmente a correção é obtida apenas
com a digitação de chmod +x <executable>. Usarei a versão de interface
de linha de comando de 64 bits denominada hashcat-cli64.bin,
compatível com as capacidades da minha máquina.
Aparentemente, os diferentes executáveis Hashcat mostrados nesse
diretório contêm diversas funcionalidade que podem ser disponibilizadas
pelos processadores de sua máquina. O outro arquivo relevante .bin, de
interesse do leitor, contém XOP acrescentado ao nome (XOP significa
eXtended OPerations instructions – instruções de operação estendida).
Caso mais tarde o leitor deseje levar a sério o uso da Hashcat, pode buscar
informações em suas flags de processador e escolher quais executáveis
podem fazer melhor uso do seu sistema em particular. Por exemplo, de
acordo com os fóruns, os chips dos processadores AMD atendem à versão
XOP.
Vamos agora tratar de rodar o executável Hashcat. A sintaxe para o
comando hashcat é a seguinte:
# hashcat [options] hashfile [mask|wordfiles|directories]
Tendo baixado (ou gerado) sua wordlist e tendo-a salvo no arquivo de
nome wordlist.txt, é hora de ir em frente. Considere este comando de
exemplo depois de introduzir o subdiretório examples com o comando cd
examples/:
# ./hashcat-cli64.bin -m0 -a0 A0.M0.hash A0.M0.word
A opção -m significa que um hash MD5 está sendo especificado e a opção -
a 0 diz para a Hashcat fazer um ataque de dicionário (também conhecido
como um straight attack – ataque direto). Como referência, caso -m1800
tenha sido especificado, o leitor está se referindo ao algoritmo moderno
preferido de hashing Unix, o SHA512.
Como o leitor está provavelmente supondo, o arquivo A0.M0.hash no
diretório examples é a sua lista de hashes. Eles são revelados sem a seção
<username>: antecedendo o sal, ou sem a senha anexada com informações
envelhecidas incluindo os dois-pontos depois dela. É dessa forma que os
hashes devem ser coletados.
O arquivo A0.M0.word é o seu dicionário potencial de senhas, como uma
wordlist.
Caso deseje escrever diretamente no arquivo sem a visualização em tela,
basta acrescentar -o <filename> ou, se desejar remover uma linha do
arquivo cheio de hashes quando já tiver descoberto sua senha, acrescentar
--remove.
Os resultados da execução do comando hashcat são mostrados a seguir
(de forma muito abreviada):
651e96f9b94e1a3a117eade5e226bd1e:y[N"%e?U{<k[`x<TlG U6Z
465133fae5a994afb03c7158260b2e8d:kCQArZz)It
oclHashcat
O uso de oclHashcat e Hashcat requer níveis de conhecimento muito
similares para as duas ferramentas, considerando que elas operam quase da
mesma forma. Embora apresentem algumas diferenças – por exemplo, a
forma como a oclHashcat carrega seus dicionários quando comparada com
a Hashcat –, podemos esperar uma curva de aprendizado sem muitos
dissabores quando movermos entre uma ferramenta e outra.
Além disso, o trabalho computacional necessário para a quebra de senhas
usa um componente totalmente diferente no sistema, como já mencionei.
Em termos simples, a oclHashcat trabalha com placas de vídeo em vez de
CPUs. Há duas importantes versões de software a considerar, cada uma
delas compreendendo duas GPUs populares:
• cudaHashcat, para uso em placas de vídeo Nvidia
• oclHashcat, que trabalha com placas de vídeo AMD
As GPUs são muito mais rápidas que as CPUs (quando configuradas
corretamente) porque são projetadas exclusivamente para realizar cálculos
extensos e complexos, usualmente no processamento de gráficos. Apesar
de obviamente projetadas para serem inerentemente rápidas, em termos de
desempenho, as CPUs podem ser sujeitas a desvios de finalidade, incluindo
conjuntos de funcionalidades, causando uma redução na capacidade de
processamento. Como resultado, as GPUs são uma boa escolha para a
computação de grandes quantidades de dados porque podem ser
otimizadas de forma muito mais efetiva. É possível também escalar as
saídas de GPUs de forma quase perfeita pela combinação de diversas delas
em cadeia, potencializando assim a capacidade de processamento. Para ter
uma ideia da rapidez das GPUs, se forem usadas rainbow tables e o
keyspace for dividido (considerando os 95 caracteres disponíveis em um
teclado americano), podem ser gerados dez trilhões de textos simples por
segundo!
Em termos de aprendizado de Hashcat e oclHashcat, recomendaria
primeiro fazer a Hashcat funcionar e depois se informar sobre como fazer
os drivers da placa de vídeo GPU trabalharem. Mais informações podem
ser obtidas em http://hashcat.net/oclhashcat/.
Como pode causar confusão, o oclHashcat-plus caiu em desuso e é
considerado obsoleto. Como resultado, não há benefícios no uso da versão
“plus”.
Hashcat-utils
Um componente adicional da suíte Hashcat que vale a pena mencionar é
um grupo de utilitários chamado Hashcat-utils. Essa coleção de
ferramentas úteis pode ser baixada de
http://hashcat.net/wiki/doku.php?id=hashcat_utils.
As ferramentas incluem o combinador, que é um programa autônomo pelo
qual se pode rodar ataques de combinadores. Mais informações podem ser
encontradas em https://hashcat.net/wiki/doku.php?
id=combinator_attack.
Um arquivo wordlist também pode ser aprimorado e dividido em partes
com a ferramenta cutb, que pode ser usada para fazer uma limpeza de
caracteres comuns indesejados anteriores ou posteriores em um arquivo
wordlist.
Outra ferramenta incluída no conjunto, a rli, é similar ao comando Unix,
e simplesmente remove arquivos duplicados, após comparar um arquivo
com um ou mais arquivos.
Definitivamente, em uma outra ocasião pode valer a pena explorar esses
utilitários para aumentar o conhecimento da forma de trabalho da
Hashcat.
Resumo
Neste capítulo, discorri sobre a teoria por trás dos ataques de senhas. Citei
também a importância do número de combinações incluídas em um
conjunto de caracteres, o comprimento das senhas e como suas
combinações afetam o keyspace. Finalmente, descrevi o hashing e a
colocação de sal, recursos que aumentam de forma significativa o tempo
necessário para quebrar uma senha.
Adquirir a habilidade de conseguir quebrar senhas de forma eficiente é algo
para muitos anos, sendo certamente uma área com muitas facetas. No
entanto, a venerável Hashcat ajuda a tornar o processo de aprendizagem
uma tarefa leve. Há também um FAQ detalhado que pode ser encontrado
em http://hashcat.net/wiki/doku.php?
id=frequently_asked_questions.
Tendo visto os métodos usados por um agressor para quebrar suas senhas
e as formas como podemos tornar esse trabalho mais difícil para ele, o
leitor deve prestar muita atenção caso descubra em suas máquinas vestígios
de qualquer uma das ferramentas já discutidas. Com o poder possibilitado
pela aquisição dos novos conhecimentos, é desnecessário lembrar que essas
habilidades devem ser usadas com responsabilidade.
1 N. do T.: Ao visitar o site na época em que este livro estava sendo traduzido, não encontrei o link
SHOW DETAILS. O site foi reformulado e agora é muito mais dinâmico: à medida em que uma
senha de exemplo é digitada, a segurança desta é calculada imediatamente e mostrada na forma de
quanto tempo é necessário para que seja quebrada.
2 N. do T.: Esclarecendo o texto do autor, o processo é “simples e inteligente” porque quando o
usuário inicialmente cadastrou sua senha, ela foi transformada em um hash que não pode ser
descriptografado. Cada vez que ele quiser entrar no sistema, a senha que ele digita na tela de login
é criptografada em um outro hash, e é esse novo hash que é comparado ao que está guardado. Se
os dois forem idênticos, a senha está correta, mas o próprio Linux não sabe qual é a senha original,
ele apenas compara os hashes.
3 N. do T.: Na última revisão deste livro, a versão mais atual era 3.20.
CAPÍTULO 10
Ataques de injeção de SQL
História
Considerando sua simplicidade, o fato da SQLi ser assim tão eficaz a torna
uma modalidade extraordinária de ataque.
Tomem nota disso, senhores desenvolvedores júniores, porque quando se
trata de assuntos de segurança, os administradores de sistema não podem
ser diretamente responsabilizados pela ocorrência desses ataques. Isso
porque, na maioria das vezes, as explorações são possíveis devido a códigos
que não escapam caracteres especiais de forma adequada. Além de sua
simplicidade, outra causa de preocupação é o fato de este tipo de ataque
ser conhecido desde 1998. Uma edição da Phrack Magazine, publicada em
dezembro daquele ano, anunciou pela primeira vez esta enorme e
arrebatadora vulnerabilidade em sites. Com o tempo, o horror continuou
aumentando, tornando-se óbvio que diversas ferramentas automatizadas
poderiam ser usadas para uma varredura na web, em busca de sites,
corrompendo ou roubando dados da forma como bem entendessem.
Porém, a coisa não parou aí. Com a popularização dos ataques phishing
(nos quais os agressores enganam os usuários, induzindo-os a revelar
informações sobre eles próprios), os ardilosos agressores passaram a
reformular completamente determinados sites, injetando neles os códigos
necessários, dando ao usuário a impressão de estar visitando um site
autêntico.
Por muitos anos, mantive um servidor ISP muito pequeno compartilhado
com usuários de relativo conhecimento tecnológico. Em pelo menos três
ocasiões, nossos clientes de compartilhamento do servidor,
involuntariamente menos zelosos com seus scripts hospedados,
sucumbiram a ataques phishing. A partir da metade dos anos 2000, em um
período de apenas poucos anos, entraram em contato conosco o FBI (U.S.
Federal Bureau of Investigation), um banco e um serviço de segurança
white hat, informando ação de hackers em servidores de clientes. Assim,
mesmo em uma organização de pequeno porte, uma cópia falsa de um site
de leilões e de dois sites bancários foram clonados e usados em ataques
phishing em nossas redes dentro de um curto espaço de tempo.
Rapidamente ficou óbvio que os ataques SQLi estavam se tornando
populares entre os intentos com finalidades maliciosas.
Os administradores de sistemas e os desenvolvedores aprenderam com isso
e, em reação, começaram a endurecer os códigos. Recordo-me que nessa
época houve um escape diligente por caracteres especiais para cada
componente de usuário de entrada em um site baseado em PHP para evitar
ataques SQLi.
SQLi básica
Como já mencionei, a premissa principal por trás da SQLi é a captura
ilegítima de códigos de um banco de dados ou a injeção de códigos nele.
Para evitar esses problemas, não se deve mais expor consultas (queries)
para o mundo externo, e para consegui-lo a melhor maneira é abolir o uso
de linguagens que rodam no servidor (como o PHP, por exemplo). O
problema é que, com isso, o site perde fluidez e utilidade. Caso não seja
possível evitar o uso dessas linguagens, é preciso certificar-se de que todos
os vetores de ataque estejam sendo monitorados. A forma mais fácil de
conseguir isso é filtrar todos os dados de entrada recebidos de visitantes.
Em outras palavras, em qualquer ponto do site em que um usuário pode
introduzir dados, devem ser tomadas precauções relevantes dentro do
código utilizado. Isso envolve a análise da entrada em um formato
amigável antes do envio dos dados ao banco de dados.
Um tutorial completo sobre como proceder para manter o código seguro
não está no escopo deste livro. De imediato, farei uma recapitulação rápida
usando uma linguagem de programação popular. Antes disso, vou
recapitular algumas formas simples de funcionamento da SQLi.
Como havia mencionado, a mera deterioração de um site não é o único
prejuízo que uma SQL interceptada pode causar. Consideremos esta
instrução SQL, por exemplo:
sql-server> DROP TABLE special-offers;
Uma tabela pode ser completamente excluída de um banco de dados se os
nomes dessa tabela forem conhecidos. Além do comportamento
destrutivo, eu não havia ainda mencionado a extração de nomes de usuário
e de senhas de um banco de dados. Para quem tem intenções criminosas,
um ataque SQL é sem dúvida um prêmio que vale a pena perseguir. Muitas
marcas comerciais poderosas foram vítimas de códigos com programação
fraca e SQLi. A longa lista de vítimas inclui empresas como Yahoo, Adobe,
LinkedIn e Sony Music. Evidentemente, sem ter sido um dos agressores
nem tendo pertencido à equipe incumbida de recuperar os serviços
afetados por esses ataques, posso somente conjeturar em qual magnitude
esses ataques envolveram SQLi. Um Palácio da Vergonha SQLi pode ser
encontrado em http://codecurmudgeon.com/wp/sql-injection-hall-
of-shame/. Apesar de essa lista não ser muito completa, tenho certeza de
que o leitor concorda ser uma leitura necessária.
Há pouco fiz referência a uma linguagem de programação. Vou usar a que
talvez seja a linguagem de script do lado servidor mais popular do mundo,
a PHP, como exemplo para uma rápida demonstração de como a SQLi
funciona. Além de ser usada diretamente em milhões de sites, a poderosa
PHP está presente no Sistema de Gerenciamento de Conteúdo (Content
Management System – CMS) mais popular do planeta, o WordPress
(https://wordpress.com), e em muitas outras aplicações dinâmicas em sites,
como a Joomla! (https://www.joomla.org). Em resumo, a PHP está presente
de forma generalizada na web, constituindo-se em um alvo fácil para os
agressores caso uma exploit seja descoberta.
Vamos ver outro exemplo, desta vez em PHP:
$input = $variable[3];
$dbquery = "SELECT id, item, price FROM specialoffers ORDER BY id
LIMIT 15 OFFSET $input;";
Observando a linha superior, podemos notar a ausência de filtragem na
variável chamada $input. Isso significa que, quando a variável é usada na
segunda linha dentro da instrução SQL, ela pode potencialmente incluir
qualquer código desejado por um atacante. Com a injeção de um desses
códigos criados pelo atacante, podem ser causados estragos de toda sorte.
Outro exemplo é a atualização da senha de usuário administrador (sysop
user). Por exemplo, uma instrução SQL normal no código PHP é parecida
com esta:
$dbquery = "UPDATE credentials SET passwd='$password' WHERE
userid='$id';";
Acrescentando SQL depois dessa instrução, tal como or userid like
'%sysop%', o SQL se torna muito menos restrito e é possível solicitar ao
banco de dados que faça uma busca rápida de outros nomes de usuários
privilegiados similares a sysop, como sysops, atualizando suas senhas nesse
processo.
De forma preocupante, é possível também executar comandos shell que
podem ser incluídos dentro da SQL. Alguns servidores de banco de dados
permitem acesso a comandos de sistemas operacionais usando esse
método.
Mitigação de SQLi em PHP
Como havia mencionado, este é um tema muito extenso para abordar em
detalhes, porém seria uma negligência da minha parte não explorar
rapidamente como filtrar entradas SQL para ajudar na mitigação de
ataques SQLi. Há um bom número de funções PHP que podem ajudar
nessa tarefa. Na época da elaboração deste livro, a Fundação PHP estava
migrando a versão estável para a 7.0.0, sendo que a versão corrente é a
5.6.16 (embora até a publicação a nova versão deva ser superior).
Podemos ressaltar que, nas versões mais antigas (anteriores à 5.3.0), dentro
do arquivo de configuração principal do PHP (php.ini) era possível filtrar
(ou escapar) todos os dados de entrada via PHP usando
magic_quotes_gpc. Aparentemente, isso foi descontinuado após a 5.3
porque a lista de caracteres a escapar era gigantesca, e nem todos eram
escapados de fato. Essencialmente, as magic quotes não foram projetadas
para fins de segurança, mas acabaram sendo improvisadas para tal.
Para proteger a variável usada no primeiro exemplo SQL, a entrada de
usuário pode ser executada com a função stripslashes. O exemplo tem
esta forma:
$input = $variable[3];
Usando stripslashes, fica parecido com:
$input = stripslashes($variable[3]);
Como o leitor deve estar imaginando, isso significa a remoção de barras
invertidas (slashes) para ajudar na proteção contra entradas indesejadas.
Há também o trim para remover espaços em branco de uma variável, que
pode ser usado da mesma forma, bem como strip_tags para remoção de
HTML e de outras etiquetas de marcação (markup tags). Todas essas
funções são úteis e podem ser encadeadas para efeitos de facilidade:
$input = stripslashes((trim($input));
Além disso, até a versão 5.5.0 da PHP, podia ser usada a função
mysql_real_escape_string para limpar strings individuais como:
$input = mysql_real_escape_string($input);
No entanto, a partir da versão 7.0.0, quase sempre é possível usar um
driver aprimorado chamado MySQLi (significa MySQL improved
[melhorado]) no lugar da SQLi. Graças a esse aperfeiçoamento, é possível
adotar uma forma mais avançada para eliminar caracteres desnecessários e
potencialmente perigosos do código em execução. Um exemplo usando
mysqli apresenta poucas diferenças em relação ao exemplo anterior:
$input= mysqli_real_escape_string($input);
Usando MySQLi, a conexão ao banco de dados é feita usando um método
diferente:
$mysqli = new mysqli("localhost", "userid", "passwd", "DB_name");
Outra forma de mitigar ataques SQLi é usar instruções preparadas. A ideia
por trás desse acréscimo de segurança é fazer o gerenciador de banco de
dados processar a linguagem SQL de forma completamente separada de
qualquer parâmetro em uso. Teoricamente, isso significa que um agressor
não tem como injetar qualquer código na consulta. Um exemplo pode ser
parecido com:
$input = $mysqli->prepare("INSERT INTO table_name (column_name) VALUES (?)");
$input->bind_param("s", $actual_user_input);
$input->execute();
$input->close();
Essa nova e preferencial abordagem realiza filtragem nos parâmetros
usando a nova biblioteca. Note o ponto de interrogação no lugar do valor
da variável. A linha contendo execute concatena todos os parâmetros
anteriores. Essa função precisa ser lida apenas uma vez, o que é uma ajuda
extra; se fosse lida diversas vezes em poucas páginas, o interpretador PHP
teria seu desempenho prejudicado.
Outra abordagem que deve ser conhecida existe desde as primeiras versões
da PHP e faz uso de objetos de dados PHP (PHP Data Objects – PDO). Há
uma grande e extensa discussão aqui:
http://stackoverflow.com/questions/60174/how-can-i-prevent-
sql-injection-in-php.
Qual metodologia é melhor para uso é algo questionável, mas a PDO
parece ser muito popular. Eis um exemplo de PDO:
$input = $pdo->prepare('SELECT * FROM special_offers_table
WHERE offer = :specialoffer');
$input->execute(array('name' => $specialoffer));
Há algumas informações (em inglês) bem escritas sobre PDO em
http://whateverthing.com/blog/2014/08/28/the-heart-of-
darkness/. A leitura vale a pena, pela simples razão de auxiliar na escolha
entre métodos de combate a ameaças SQLi na última versão da PHP
(versão 7.0.0 em diante).
Lançamento de um ataque
Vamos ver agora a essência da funcionalidade sqlmap, especificamente
voltada ao comprometimento de uma máquina remota.
No entanto, esteja ciente disto: para testar suas próprias habilidades na
sqlmap, o leitor precisará configurar seu próprio servidor de teste para
torná-lo vulnerável ou identificar sites legítimos vulneráveis a ataques, e as
duas coisas consomem bastante tempo. Devido à forma como os URLs são
formados, é surpreendentemente fácil para o Google identificar sites
vulneráveis. Nem é preciso dizer, neste caso, que desencorajo ataques em
qualquer site encontrado via Google ou por qualquer outro método. Para
descobrir URLs potencialmente exploráveis, pode ser emitida uma consulta
como inurl:website.php?id= ou inurl:product.php?id=. O primeiro
termo de busca retorna preocupantes 1,7 milhão de resultados.
Os sites e outros recursos online que de forma incompetente deixam
expostas suas vulnerabilidades via Google ganharam um apelido:
Googledorks (bobocas do Google). Vale a pena dar uma rápida olhada em
alguns deles, relacionados no site www.hackersforcharity.org/ghdb/. As
listas incluem muitos dados potencialmente secretos, como páginas de
login, diretórios sensíveis e arquivos com nomes de usuários. Use essas
informações com responsabilidade.
Alternativamente, a sqlmap pode rodar via Python, o que significa a
necessidade de alguma versão dessa linguagem instalada na máquina.
Na Figura 10.1 podemos ver que os desenvolvedores são cautelosos o
suficiente para manter distância segura de atividades ilegais. Essas
ferramentas poderosas estão sempre sujeitas a abusos.
Figura 10.1 – Apresentação da sqlmap logo após seu lançamento, incluindo a
isenção de responsabilidade (legal disclaimer).
No exemplo a seguir, a sintaxe a ser usada para o comando sqlmap é muito
simples:
# python sqlmap.py -u http://www.a-vulnerable-website.com/product.php?id=1111
Se houver problemas com baixa conectividade ou com respostas lentas do
servidor de banco de dados remoto, a inclusão de --time-sec 10 no
comando atua no sentido de introduzir um ajuste de temporização mais
realista. Parece uma maneira não muito intuitiva, mas isso realmente
acelera o processo de forma geral.
Vamos agora, de forma metódica, ver alguns poucos comandos simples. O
leitor pode escolher encadeá-los juntos se já estiver familiarizado com o
uso da sqlmap.
O meu comando de exemplo sqlmap inclui a opção -u, significando que
um URL está especificado. Esse comando apenas verifica as
vulnerabilidades do parâmetro final (id=1111) usando diversos testes de
injeção SQL. Com isso, a sqlmap pode obter algumas informações, como o
fabricante e a versão do servidor web, o sistema operacional remoto e a
versão do servidor do banco de dados.
Deseja saber os nomes dos bancos de dados usados pelo site? Isso pode ser
obtido pelo acréscimo da opção --dbs:
# python sqlmap.py -u "http://www.a-vulnerable-website.com/product.php?id=1111" -
-dbs
Com essas informações úteis em mãos, o próximo passo é descobrir os
nomes das tabelas em uso. Isso pode ser feito substituindo o nome do
banco de dados real pela entrada <database-name>:
# python sqlmap.py -u "http://www.a-vulnerable-website.com/product.php?id=1111" -
-tables -D <database-name>
O próximo passo lógico é saber quais são as colunas usadas por uma tabela
de banco de dados de interesse com a entrada <database-name> e também
<table-name> com o nome da tabela:
# python sqlmap.py -u "http://www.a-vulnerable-website.com/product.php?id=1111" -
-columns -D <database-name> -T <table-name>
A parte final do processo é extrair todos os dados do banco de dados alvo.
Isso inclui nomes de usuário e senhas, informações pessoais ou,
simplesmente, informações de produtos de uma loja online. No caso de
ataque a um site remoto, o valor das informações extraídas é claramente
dependente do site em questão. Para fazer o despejo dos dados do banco
de dados, devemos usar a opção --dump:
# python sqlmap.py -u "http://www.a-vulnerable-website.com/product.php?id=1111" -
-dump --columns -D <database-name> -T <table-name>
Caso deseje extrair apenas colunas específicas, elas devem ser especificadas
diretamente. Uma vez conhecidos os nomes das colunas, elas podem ser
simplesmente listadas com uma opção como -C columnX, columnY e
separadas com vírgulas. Feito isso, basta remover a opção --columns
incluída no exemplo anterior.
O último comando pode produzir uma saída parecida com esta:
+-------+----------------+----------+--------+------------+--------------+
| id | title | color | price | category | received-date|
+-------+----------------+----------+--------+------------+--------------+
| 1111 | bars of soap | green | 1.22 | toiletries | 11.11.22 |
+-------+----------------+----------+--------+------------+--------------+
Caso seja um desenvolvedor ou um administrador de sistemas e não esteja
preocupado com a rapidez de um despejo de banco de dados, é melhor
passar a se preocupar. Tenha em mente que a identificação de uma lista de
alvos potenciais pode ter sido feita via Google, com um mínimo de esforço
e com poucos comandos sendo usados, conseguindo com isso realizar o
roubo de dados comerciais potencialmente valiosos. Além desse roubo de
dados, com o uso de sqlmap os dados existentes podem ser sobrescritos e o
serviço online em questão corrompido, afetando a marca e a reputação
com relativa facilidade.
A poderosa e sofisticada ferramenta sqlmap oferece uma longa lista de
opções simplesmente muito grande para ser abordada em detalhes. Minha
sugestão é a leitura da página GitHub, que contém maior detalhamento do
uso da sqlmap:
https://github.com/sqlmapproject/sqlmap/wiki/Usage.
Resumo
Neste capítulo, abordei os princípios básicos por trás da injeção SQL e
também apresentei um breve histórico dos ataques SQL. Além disso, vimos
como os desenvolvedores PHP recomendam ações de proteção contra
ataques SQLi relacionados com MySQL, no passado com versões mais
antigas e prosseguindo com as versões mais novas, particularmente após a
versão 7.0.0.
É fácil compreender porque os ataques SQLi são tão comuns – e de fato já
foram considerados como o tipo de ataque mais popular em alguns
contextos. Pelo uso de alguns poucos comandos sqlmap relativamente
simples, pode-se de forma poderosa abrir brechas na segurança de um site,
pesquisar e roubar seus dados valiosos, causando danos na reputação com
esse vandalismo.
É importante, para o pessoal técnico encarregado da segurança de
sistemas, estar ciente da simplicidade desses ataques e compreender as
implicações resultantes de equívocos aparentemente simples. Esses
equívocos podem deixar sites – construídos com muitos esforços e recursos
– vulneráveis a ataques devastadores que demandam um trabalho
considerável para a sua recuperação. Nunca é demais lembrar: esses
conhecimentos devem ser usados com responsabilidade. Há muito mais
satisfação em proteger adequadamente sua própria infraestrutura e menos
em realizar ataques em infraestrutura de terceiros.
Guia Prático de Cifragem Manual
Ribeiro, Fred
9788575226230
104 páginas