Em meu artigo anterior, pude demonstrar um contêiner Kali Linux rodando com o Navegador Tor e conectado ao seu ambiente de desktop com um cliente VNC. Verifiquei que o Navegador Tor estava se conectando à Rede Tor durante uma sessão de navegação. Essa configuração me permitirá simular o tipo de tráfego que pode vir de um invasor visando um site.
Neste experimento, usarei o Selenium para automatizar o Navegador Tor para sintetizar pressionamentos de tecla e eventos de navegação por meio da interface do WebDriver do navegador. Cada rastreador terá um endereço IP aleatório fornecido pelo Tor Proxy incorporado para evitar a detecção. Depois de salvar os resultados como objetos JSON no sistema de arquivos local, usarei o Python para processá-los em um único arquivo CSV. Por fim, discutirei quais contramedidas podem ser aplicadas em um data center e no lado do cliente para tentar detectar, limitar a taxa e bloquear a atividade do bot.
Todos os arquivos e licenças aplicáveis estão disponíveis neste repositório de código aberto: tor-driver-python
Tenho experiência em automação de teste e passei muitas horas projetando testes. Também passei muito tempo trabalhando com o Selenium e o usei em várias linguagens de programação e configurações diferentes para automatizar navegadores da Web para fins de teste. Existem cenários onde só é possível testar uma aplicação web com um navegador real, e o Selenium é uma ótima ferramenta para isso.
Em meu trabalho como engenheiro de DevOps, passei muito tempo me preocupando com o que fazer com os rastreadores da Web que estão atingindo e, às vezes, atacando diretamente os aplicativos da Web pelos quais sou responsável. Achei que seria uma experiência interessante explorar o outro lado dessa questão pela primeira vez.
Quero ver o quão perto eu poderia chegar de simular um ataque de um botnet para fins educacionais e discutir métodos de combate a coisas como tráfego de rede Tor suspeito em um Data Center moderno. Botnets são comumente usados para realizar ataques de preenchimento de credenciais. Usarei uma técnica semelhante para pesquisar consultas e coletar informações da web.
O preenchimento de credenciais é a injeção automatizada de pares de nome de usuário e senha roubados (“credenciais”) nos formulários de login do site, a fim de obter acesso fraudulento às contas de usuário. 1
A fim de evitar questões éticas, ao mesmo tempo em que tenta permanecer fiel à tarefa. Estou fazendo as seguintes alterações no cenário:
robots.txt
permissivos, e os Termos e Condições foram verificados no momento da redação, o que não exclui o rastreamento. Por exemplo , os Termos e Condições do IMDB proíbem explicitamente o rastreamento sem consentimento por escrito.
O Protocolo de exclusão de robôs é uma maneira de os webmasters informarem aos rastreadores onde eles estão e onde não podem coletar informações. Mais informações e exemplos podem ser encontrados no site robotstxt.org . Encontrei um artigo: Lista de mecanismos de pesquisa alternativos enquanto tentava encontrar um que permitisse a raspagem da web na página de resultados da pesquisa. Abaixo está um resumo dessa pesquisa.
Mecanismo de busca | URL robots.txt | Rastejar é permitido? |
---|---|---|
Não, mas tem uma API | ||
Não, mas tem uma API | ||
Não | ||
Não, mas tem uma API | ||
Sim, mas não exatamente o que eu estava procurando | ||
Sim |
Alguns outros recursos que achei úteis ao pesquisar este tópico:
Vou evitar o uso de outras bibliotecas além do Selenium para este exemplo. Existem alguns padrões realmente básicos que quero demonstrar e não quero ficar atolado com uma linguagem específica de domínio (DSL) específica que pode dificultar a compreensão do que está acontecendo.
No entanto, acho que usar uma estrutura de execução de teste é uma ótima maneira de organizar esse tipo de código. Adicionar uma estrutura pode resolver muitos problemas relacionados à estrutura geral do código, lógica de repetição e até relatórios.
Existe um padrão básico de como manipulo uma página em uma sessão do WebDriver. Eu também adiciono uma pausa após cada ação executada. A automação do navegador pode ser esquisita. Os tempos limite adicionam muita estabilidade ao rastreamento e limitam muito as chances de obter taxa limitada e bloqueada. Sempre que necessário, também incremento o rastreamento com chamadas de API para outros mecanismos de pesquisa ou fontes de informação.
Adotei uma abordagem muito simples para os seletores. Estou usando os seletores xpath e css que estão disponíveis no navegador. Concentrando-se principalmente em tags de âncora e fragmentos de URL para navegar entre as páginas durante um rastreamento.
Estou usando condições esperadas para esperar que os elementos estejam presentes antes de tentar clicar neles. O projeto Selenium tem muita documentação, mas também achei a discussão sobre condições de espera com usos de exemplo no Stack Overflow um recurso inestimável.
Existe um projeto PyPi existente chamado tbselenium que tem uma função semelhante. Para esta experiência, fiz referência à configuração do perfil do Firefox, mas não precisei de nenhum dos outros recursos que o tbselenium inclui. A complexidade adicional dos contêineres sem acesso root estava contribuindo para tornar a depuração mais difícil. Isso aumentou a motivação para limitar as dependências e tentar soluções pré-existentes simples. Por exemplo, há muitos lugares onde estou usando ferramentas linux e sub-shells em vez de implementar soluções python puras diretamente.
A classe finalizada tem aproximadamente 150 linhas de Python. Acho que será mais fácil analisar o que está acontecendo em profundidade com menos para revisar. Aprendi muito sobre como o Tor Browser Launcher funciona e como configurar os perfis do Firefox. Este perfil foi reunido de várias fontes online e eles são mencionados no código-fonte, bem como neste documento.
Eu abstraí a inicialização, desmontagem e uma parte muito comum da lógica de navegação em uma classe chamada TorDriver
. É uma classe muito simples que configura um perfil do Firefox com o Tor Browser Launcher. Ele possui um método para verificar se um elemento está visível na página e outro que verifica se o soquete do proxy está funcionando. A configuração e a depuração do perfil do Firefox foram amplamente informadas por uma discussão do Stack Overflow: Open Tor Browser with Selenium .
O arquivo completo pode ser encontrado aqui: tor-driver-python/torDriver.py
Importação de selênio, pprint, subprocesso e soquete para os componentes de configuração e WebDriver.
O método a seguir abstrai a verificação de um elemento e retorna True
ou False
se estiver visível dentro de um tempo limite.
A porta proxy precisa estar ativa antes de enviar sinais para ela. Seguindo alguns exemplos no Stack Overflow sobre como testar conexões de soquete em Python, descobri isso:
A maior parte do módulo é uma classe que controla o perfil do Firefox, baixa o geckodriver e inicia o torbrowser-launcher.
Aqui eu tenho uma configuração básica e algumas formas de substituir as coisas, mas principalmente mantendo isso o mais simples possível:
O perfil do Firefox precisa ser configurado no mínimo para se conectar à porta do proxy, também desativei o javascript com ele.
Isso usa o perfil e o binário do TorDriver para inicializar um driver
Adicionando um método para baixar e extrair o geckodriver em um subprocesso. Vale a pena mencionar que, de alguma forma, ao executá-lo no contêiner, o tar.gz
não é mais compactado e simplesmente precisa ser desarquivado. Mais informações sobre o erro estão disponíveis aqui: stdin: not in gzip format error
Até que o soquete responda, tente novamente uma conexão com a porta do proxy:
Neste exemplo, usei a seguinte abordagem em duas fases. A primeira fase é a coleta de informações e a fase subsequente é o processamento das informações. Dessa forma, não estou vinculado à conectividade de rede durante todo o processo e posso tentar analisar novamente os resultados quantas vezes forem necessárias sem voltar ao material de origem.
O arquivo completo pode ser encontrado aqui: tor-driver-python/crawler.py
O rastreador lê um arquivo de texto e usa essas informações para preencher as consultas na sessão do WebDriver. O estado do rastreamento é mantido em uma pasta de arquivos json, um por consulta. Eu tento fazer o processamento mínimo absolutamente necessário para exportar as informações uma vez e qualquer processamento subsequente pode acontecer nos dados existentes, em vez de voltar ao(s) site(s).
Estou usando um arquivo de texto para armazenar pesquisas. Escolhi um arquivo de texto porque é muito fácil de reestruturar. A edição de texto é uma barreira baixa para iniciar um rastreamento com novas informações ou para retomar um que falhou no meio do caminho. Se esse rastreador tivesse requisitos de dados mais complexos, eu consideraria usar um banco de dados. Isso permitirá a implementação de uma API para controlar varreduras com uma interface de usuário personalizada, para geração de relatórios.
Arquivos de exemplo já estão na pasta de resultados no repositório: tor-driver-python/results
Em um rastreador mais robusto, sugiro usar uma tecnologia de banco de dados real. Isso é suficiente para saber facilmente onde a coleta de dados parou e facilitar a reinicialização.
O rastreador pode ser executado a partir do contêiner com os seguintes comandos. O gerador de relatórios requer a presença de arquivos JSON, exemplo de arquivo CSV de exportação pode ser encontrado aqui:
Inicie o contêiner:
docker run -it --rm -p 5901:5901 -v "${HOME}/src":/src excitingtheory/kalilinux-xvfb:torbrowser
Inicie um servidor VNC no contêiner, ele solicitará senhas de sessão:
/opt/start-vnc-server-once.sh
Comece o rastreamento de dentro da sessão VNC:
python3 crawler.py
O rastreador aguardará a inicialização do navegador Tor e, infelizmente, é uma etapa manual. Basta clicar na caixa de seleção e clicar em conectar. Veja o vídeo de demonstração para um exemplo.
O script de relatório gerará um arquivo de valor separado por vírgula (CSV) do
Arquivos de resultado de JavaScript Object Notation (JSON ) que o rastreador salva durante o rastreamento. Escolhi o formato CSV porque é um formato mais comum para compartilhar com colegas, mas ainda fácil de importar para outras ferramentas para análise posterior.
O arquivo completo pode ser encontrado aqui: tor-driver-python/report.py
Isso usa bibliotecas Python integradas para ler JSON, gravar CSV e analisar URLs para formatação e apresentação de dados. Em seguida, percorre os resultados e os carrega para iniciar o processamento de dados.
Esta é a funcionalidade principal do gerador de relatórios. Isso faz uma apresentação final e ordenação dos dados capturados nos objetos de resultados. Normalmente, os URLs são úteis apenas para o movimento funcional dos rastreadores em um site, e não como uma captura de dados final, mas é um bom começo para personalizar a extração de dados adicionais.
Os resultados do rastreamento são salvos no diretório ./results
como arquivos JSON. Usarei o seguinte script para gerar um relatório a partir dos dados.
python3 report.py
Um exemplo de arquivo CSV de saída pode ser encontrado aqui: tor-driver-python/output.csv
Existem algumas maneiras diferentes de detectar e mitigar a atividade do Bot. Vou me concentrar principalmente no lado do Data Center, mas também discutirei alguns métodos de detecção do lado do cliente. O cliente nunca pode ser realmente confiável, pois os sinais do lado do cliente podem mudar a qualquer momento e podem ser falsificados. Acho que é importante ter isso em mente ao projetar um sistema de detecção. No Data Center existem duas formas de proteção que discutirei: limitação de taxa e bloqueio de reputação.
Existem algumas maneiras de detectar uma sessão ativa do WebDriver no lado do cliente apenas com javascript: um problema relacionado no Github entra em mais detalhes . Essencialmente, como o protocolo WebDriver altera os objetos de documento e janela, ele pode ser detectado no código do lado do cliente.
Vou me concentrar nas soluções com as quais tenho mais experiência, Fastly, AWS WAF e Nginx. CloudFlare foi uma surpresa total, então vou falar sobre a oferta deles também.
As regras baseadas em taxa do AWS Web Application Firewall (WAF) também podem ser usadas para bloquear os níveis de atividade de negação de serviço, e há regras padrão que também podem ser usadas para detectar o tráfego de rede Tor, consulte a documentação da regra de reputação de IP para obter mais informações. Outra abordagem comum é bloquear todo o tráfego de outros data centers, o que é seguro se o público-alvo for o consumidor. No entanto, as empresas podem estar usando VPN em nuvem e outras tecnologias que podem tornar isso prejudicial ao tráfego legítimo.
O Signal Science da Fastly, uma solução muito popular, pode ser usado para detectar especificamente o tráfego do Tor. Primeiro, eles podem proteger contra ataques DDOS, consulte a página de mitigação de DDOS para obter mais informações. Em segundo lugar, eles podem detectar o tráfego do Tor e bloqueá-lo. Aqui está a documentação Usando Sinais do Sistema que cobre isso.
Para o Nginx, existem alguns artigos sobre como fazer isso também: Como bloquear o tráfego anônimo com o Nginx ou dentro do seu aplicativo da web . Essencialmente, chamando as APIs para obter informações sobre os nós de saída do Tor, as regras de bloqueio de IP podem ser geradas e aplicadas ao Nginx em uma programação.
Em um contraste surpreendente com os provedores de nuvem acima, CloudFlare está oferecendo suporte para clientes Tor. Me deparei com a documentação de suporte do Tor!? onde eles discutem a capacidade de servir conteúdo para usuários Tor da rede. Acho que essa é uma abordagem realmente interessante e estou ansioso para explorá-la ainda mais no futuro.
O WebDriver é uma ferramenta poderosa para testes e também pode ser usado para coletar informações em locais onde o acesso a uma API não é viável. Por exemplo: o acesso é restrito, censurado, muito caro ou geralmente bloqueado por práticas anticompetitivas. Melhor ainda é combinar os dados coletados do rastreamento da Web com as informações coletadas das APIs.
Este é um exercício importante porque está ficando cada vez mais difícil impedir o tráfego malicioso de Bots, e não é uma boa prática de segurança esperar até que um ataque ocorra para considerar como mitigá-lo. Acredito que todos os responsáveis por colocar informações online devem saber como as informações violadas serão usadas contra os sistemas pelos quais são responsáveis. Em um cenário simplificado, com restrições éticas, demonstrei isso fazendo o seguinte: