Hoje em dia, muitos incidentes de segurança na web envolvem automação. Ataques de raspagem de dados da web, reutilização de senhas e fraude de cliques são realizados por agentes mal-intencionados que tentam imitar usuários reais e, portanto, procuram parecer que estão acessando por meio de um navegador. Como proprietário de um site, você quer garantir que seu conteúdo seja disponibilizado a pessoas; como provedor de serviços web, você quer que o acesso programático ao seu conteúdo seja feito por meio da sua API, em vez de ser extraído pela sua interface web, que é mais pesada e menos estável.
Supondo que você tenha verificações básicas para visitantes semelhantes ao cURL, a próxima etapa razoável é garantir que os visitantes estejam usando navegadores reais, com interface gráfica — e não navegadores sem interface gráfica, como PhantomJS e SlimerJS.
Neste artigo, vamos demonstrar algumas técnicas para identificar acessos feitos pelo PhantomJS. Decidimos nos concentrar no PhantomJS porque ele é o ambiente de navegador sem interface gráfica mais popular, mas muitos dos conceitos que abordaremos também se aplicam ao SlimerJS e a outras ferramentas.
OBSERVAÇÃO: As técnicas apresentadas neste artigo se aplicam tanto ao PhantomJS 1.x quanto ao 2.x, salvo indicação explícita em contrário. Para começar: é possível detectar o PhantomJS sem sequer responder a ele?
Pilha HTTP
Como você já deve saber, o PhantomJS é desenvolvido com base no framework Qt. A forma como o Qt implementa a pilha HTTP faz com que ele se diferencie de outros navegadores modernos.
Primeiro, vamos dar uma olhada no Chrome, que envia os seguintes cabeçalhos:

No PhantomJS, no entanto, a mesma solicitação HTTP tem esta aparência:

Você notará que os cabeçalhos do PhantomJS diferem dos do Chrome (e, como se constata, dos de todos os outros navegadores modernos) em alguns aspectos sutis:
- O cabeçalho Host aparece por último
- O valor do cabeçalho Connection combina letras maiúsculas e minúsculas
- O único valor de Accept-Encoding é gzip
- O User-Agent contém “PhantomJS”
Ao verificar essas anomalias nos cabeçalhos HTTP no servidor, deve ser possível identificar um navegador PhantomJS.
Mas será que é seguro confiar nesses valores? Se um invasor usar um proxy para reescrever os cabeçalhos antes que eles cheguem ao navegador sem interface gráfica, poderá modificá-los para que pareçam vir de um navegador moderno comum.
Parece que lidar com esse problema exclusivamente no servidor não é uma solução infalível. Então, vamos ver o que pode ser feito no lado do cliente usando o ambiente JavaScript do PhantomJS.
Verificação do User-Agent no lado do cliente
Talvez não possamos confiar no valor de User-Agent fornecido via HTTP, mas e no lado do cliente?

Infelizmente, é igualmente trivial alterar os valores do cabeçalho user-agent e de navigator.userAgent no PhantomJS, portanto isso talvez não seja suficiente.
Plugins
navigator.plugins contém uma lista dos plugins presentes no navegador. Entre os plugins mais comuns estão Flash, ActiveX, suporte a applets Java e o “Auxiliar de Navegador Padrão”, um plugin que indica se este é o navegador padrão no OS X. Em nossa pesquisa, a maioria das instalações novas dos navegadores mais comuns inclui pelo menos um plugin padrão — até mesmo em dispositivos móveis.
Isso é diferente do PhantomJS, que não implementa nenhum plugin nem oferece uma maneira de adicionar um (usando a API do PhantomJS).
A verificação a seguir pode ser útil nesse caso:

Por outro lado, é bastante simples falsificar essa lista de plugins modificando o ambiente JavaScript do PhantomJS antes que a página seja carregada.
Também não é difícil imaginar uma versão personalizada do PhantomJS com plugins reais e funcionais. Isso é mais fácil do que parece, pois o framework Qt, no qual o PhantomJS se baseia, fornece uma API nativa para implementar plugins.
Temporização
Outro ponto interessante é como o PhantomJS suprime as caixas de diálogo do JavaScript:

Após realizar várias medições, parece que, se a caixa de diálogo de alerta for fechada em até 15 milissegundos, provavelmente o navegador não está sendo controlado por uma pessoa. No entanto, usar essa abordagem significa incomodar usuários reais com um alerta que eles terão de fechar manualmente.
Propriedades globais
O PhantomJS 1.x expõe duas propriedades no objeto global:

No entanto, essas propriedades fazem parte de um recurso experimental e podem mudar no futuro.
Ausência de recursos do mecanismo JavaScript
Atualmente, o PhantomJS 1.x e 2.x usam mecanismos WebKit desatualizados, o que significa que alguns recursos presentes em navegadores mais recentes não existem no PhantomJS. Isso também se aplica ao mecanismo JavaScript — algumas propriedades e métodos nativos são diferentes ou não estão disponíveis no PhantomJS.
Um desses métodos é Function.prototype.bind, que não está disponível no PhantomJS 1.x e em versões anteriores. O exemplo a seguir verifica se bind está presente e se não foi falsificado no ambiente de execução.

Este código é um pouco complexo demais para ser explicado em detalhes aqui, mas você pode saber mais em nossa apresentação.
Rastreamentos de pilha
Os erros gerados pelo código JavaScript avaliado pelo PhantomJS por meio do comando evaluate contêm um rastreamento de pilha que pode ser identificado de forma única, permitindo-nos identificar o navegador sem interface gráfica.
Por exemplo, suponha que o PhantomJS chame evaluate no seguinte código:

Observe que este exemplo usa uma função personalizada indexOfString(), cuja implementação fica como exercício para o leitor, pois o método nativo String.prototype.indexOf pode ser manipulado pelo PhantomJS para sempre retornar um resultado negativo.
Agora, como fazer um script do PhantomJS avaliar esse código? Uma técnica é sobrescrever algumas funções da API do DOM usadas com frequência e que provavelmente serão chamadas. Por exemplo, o código abaixo sobrescreve document.querySelectorAll para inspecionar o rastreamento de pilha do navegador:

Resumo
Neste artigo, analisamos 7 técnicas diferentes para identificar o PhantomJS, tanto no servidor quanto por meio da execução de código no ambiente JavaScript do cliente do PhantomJS. Ao combinar os resultados da detecção com um mecanismo de resposta robusto — por exemplo, tornando uma página dinâmica inerte ou invalidando o cookie da sessão atual —, você pode criar um obstáculo significativo para visitantes que usam o PhantomJS. No entanto, tenha sempre em mente que essas técnicas não são infalíveis e que um adversário sofisticado acabará conseguindo contorná-las.
Para saber mais, recomendamos assistir a esta gravação da nossa apresentação na AppSec USA 2014 (slides). Também criamos um repositório no GitHub com exemplos de implementação — e possíveis formas de contornar — as técnicas apresentadas aqui.
Agradecemos pela leitura e boa caçada.
Colaboradores
Sergey Shekyan – @sshekyan
Ben Vinegar – @bentlegen
Bei Zhang – @ikarienator
Sobre o autor
Publicações relacionadas no blog

Entrega e proteção de agentes de IA em fábricas de IA: F5 para a arquitetura de referência NVIDIA OpenShell para agentes de IA seguros
As soluções da F5 ampliam a Arquitetura de Referência NVIDIA OpenShell para agentes de IA seguros.
Como medir – e minimizar – o custo total de propriedade do seu Kubernetes
O Kubernetes pode ser baixado e executado gratuitamente, mas sua manutenção está longe de não ter custos. Assim como outras grandes plataformas de código aberto que são “gratuitas” apenas em um sentido simplista, o Kubernetes quase certamente exigirá investimentos para ser implantado e operado.
As-Code: a pilha de TI contínua
Infraestrutura, configuração, pipeline, operações. De repente, tudo é “como código”. Lori MacVittie busca esclarecer a terminologia e identificar os diferentes componentes de uma stack contínua de TI.
O estado da entrega de aplicações em 2017: automação, APIs e DevOps
Explore o relatório State of Application Delivery de 2017. Leia o blog retrospectivo da F5 sobre o início da ascensão das redes declarativas e dos pipelines de DevOps.
DevOps Summit: onde a rede foi convidada para a festa
No DevOps Summit NY, falou-se muito não apenas sobre DevOps, mas também sobre contêineres, IoT e microsserviços. As sessões se concentraram não só na mudança cultural necessária para crescer em escala com uma abordagem DevOps, mas também fizeram questão de incluir...
F5 e Nutanix convergem em infraestrutura no .NEXT
Aplicações empresariais como Microsoft SharePoint e Exchange, juntamente com a VDI, continuam sendo a espinha dorsal da sua empresa. A produtividade, embora não seja tão atraente quanto o lucro, é um fator essencial para o sucesso das operações empresariais atuais. Deixar de...