Pular para conteúdo

testcookie: Módulo de mitigação de robôs testcookie do NGINX

Instalação

Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:

  • RedHat Enterprise Linux 7, 8, 9 e 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 e Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-testcookie
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-testcookie

Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:

load_module modules/ngx_http_testcookie_access_module.so;

Este documento descreve o nginx-module-testcookie v1.28 lançado em 19 de julho de 2022.


testcookie-nginx-module é um módulo simples de mitigação de robôs que utiliza um desafio/resposta baseado em cookies.

Os cookies de desafio podem ser definidos usando diferentes métodos:

  • "Set-Cookie" + redirecionamento HTTP Location 302/307
  • "Set-Cookie" + redirecionamento HTML meta refresh
  • Template personalizado, JavaScript pode ser usado aqui.

Para evitar a análise automática, o valor do cookie de desafio pode ser criptografado com AES-128 em modo CBC usando uma chave e iv personalizados/aleatórios, e depois descriptografado no lado do cliente com JavaScript.

Diretivas

testcookie

sintaxe: testcookie (on|off|var);

padrão: off

contexto: http, server, location, if

on - Habilitar módulo

off - Desabilitar módulo

var - Não interceptar solicitações, apenas definir variáveis do módulo.

testcookie_name

sintaxe: testcookie_name <string>

padrão: TCK

contexto: http, server, location

Define o nome do cookie.

testcookie_domain

sintaxe: testcookie_domain <string>

padrão: none, definido pelo navegador

contexto: http, server, location

Define o domínio do cookie.

testcookie_expires

sintaxe: testcookie_expires <string>

padrão: 31 Dec 2037 23:55:55 GMT

contexto: http, server, location

Define o valor de expiração do cookie.

testcookie_path

sintaxe: testcookie_path <string>

padrão: /

contexto: http, server, location

Define o caminho do cookie, útil se você planeja usar chaves diferentes para localizações.

testcookie_samesite

sintaxe: testcookie_samesite <string>

padrão: None

contexto: http, server, location

Define o atributo do cookie, permite declarar se seu cookie deve ser restrito a um contexto de primeiro partido ou mesmo site. O padrão é None (Cookies serão enviados em todos os contextos, ou seja, o envio cross-origin é permitido.) Aceita valores: Lax, Strict, None.

testcookie_secret

sintaxe: testcookie_secret <string>

padrão: diretiva de configuração obrigatória

contexto: http, server, location

String secreta, usada no cálculo do cookie de desafio, deve ter 32 bytes ou mais, é melhor que seja longa, mas estática para evitar a redefinição do cookie para usuários legítimos a cada reinício do servidor. Se definido como "random" - uma nova chave secreta será gerada a cada reinício do servidor, não recomendado (todos os cookies com a chave anterior serão inválidos).

testcookie_session

sintaxe: testcookie_session <variable>

padrão: diretiva de configuração obrigatória

contexto: http, server, location

Define a entrada da função de geração de desafio, * $remote_addr - endereço IP do cliente será usado como um identificador único do usuário * $remote_addr$http_user_agent - IP do cliente + User-Agent

testcookie_arg

sintaxe: testcookie_arg <string>

padrão: none

contexto: http, server, location

Define o nome do parâmetro GET, usado para o cálculo de tentativas de definição de cookie,

Se não definido - o servidor tentará definir o cookie infinitamente.

testcookie_max_attempts

sintaxe: testcookie_max_attempts <integer>

padrão: 5

contexto: http, server, location

Define o número máximo de redirecionamentos antes que o usuário seja enviado para a URL de fallback, de acordo com o RFC1945 não pode ser mais que 5.

Se definido como 0 - o servidor tentará definir o cookie infinitamente (na verdade, o navegador mostrará a página de erro).

testcookie_p3p

sintaxe: testcookie_p3p <string>

padrão: none

contexto: http, server, location

Define a política P3P.

testcookie_fallback

sintaxe: testcookie_fallback <script>

padrão: none

contexto: http, server, location

Define a URL de fallback, para a qual o usuário será redirecionado após o número máximo de tentativas, especificado pela diretiva testcookie_max_attempts ser excedido. Variáveis de script do Nginx podem ser usadas aqui. Se não definido - o cliente receberá 403 após o número máximo de tentativas.

testcookie_whitelist

sintaxe: testcookie_whitelist <network list>

padrão: none

contexto: http, server

Define as redes para as quais o teste não será utilizado, adicione redes de mecanismos de busca aqui. Atualmente apenas CIDR IPv4.

testcookie_pass

sintaxe: testcookie_pass $variable;

padrão: none

contexto: http, server

Define o nome da variável para testar se a verificação do cookie deve ser ignorada. Se o valor da variável for definido como 1 durante a solicitação - a verificação do cookie não será realizada. Pode ser usado para uma lista de permissões mais complexa.

testcookie_redirect_via_refresh

sintaxe: testcookie_redirect_via_refresh (on|off);

padrão: off

contexto: http, server, location

Define cookie e redireciona usando meta refresh HTTP, necessário se testcookie_refresh_template for usado.

testcookie_refresh_template

sintaxe: testcookie_refresh_template <string>

padrão: none

contexto: http, server, location

Use HTML personalizado em vez de um simples meta refresh HTTP, você precisa definir o cookie manualmente a partir do template. Todas as variáveis do nginx estão disponíveis e

$testcookie_nexturl - URL para a qual o cliente deve ser redirecionado, se max_attempts for excedido, o valor de *testcookie_fallback* estará aqui
$testcookie_got - valor do cookie recebido do cliente, vazio se não houver cookie ou se não corresponder ao formato
$testcookie_set - valor correto do cookie que estamos esperando do cliente
$testcookie_ok - usuário passou no teste (1 - passou, 0 - não passou) Nota: alterado de "yes"/"no" na v1.10

Além disso, se testcookie_refresh_encrypt_cookie estiver habilitado, há mais três variáveis:

$testcookie_enc_key - chave de criptografia (32 dígitos hexadecimais)
$testcookie_enc_iv - iv de criptografia (32 dígitos hexadecimais)
$testcookie_enc_sec - valor do cookie criptografado (32 dígitos hexadecimais)

testcookie_refresh_status

sintaxe: testcookie_refresh_status <code>

padrão: 200

contexto: http, server, location

Use um código de status HTTP personalizado ao servir HTML.

testcookie_deny_keepalive

sintaxe: testcookie_deny_keepalive (on|off);

padrão: off

contexto: http, server, location

Feche a conexão logo após definir o cookie, não há razão para manter conexões com robôs.

testcookie_get_only

sintaxe: testcookie_get_only (on|off);

padrão: off

contexto: http, server, location

Processar apenas solicitações GET, solicitações POST serão ignoradas.

testcookie_https_location

sintaxe: testcookie_https_location (on|off);

padrão: off

contexto: http, server, location

Redirecionar o cliente para o protocolo https após definir o cookie, também afeta $testcookie_nexturl, útil com offload SSL de terceiros.

sintaxe: testcookie_refresh_encrypt_cookie (on|off);

padrão: off

contexto: http, server, location

Criptografar a variável do cookie, usada com testcookie_refresh_template para forçar a descriptografia do lado do cliente com AES-128 CBC.

sintaxe: testcookie_refresh_encrypt_cookie_key <32 hex digits|random>

padrão: diretiva obrigatória se a criptografia estiver habilitada

contexto: http, server, location

Define a chave de criptografia.

Valores possíveis:

random - nova chave gerada a cada reinício do nginx
32 hex digits - chave estática, útil se você planeja ofuscar profundamente no JavaScript do lado do cliente.

testcookie_refresh_encrypt_iv

sintaxe: testcookie_refresh_encrypt_iv <32 hex digits|random|random2>

padrão: random

contexto: http, server, location

Define o iv de criptografia.

Valores possíveis: random - novo iv gerado para cada solicitação do cliente random2 - novo iv gerado para cada reinício do nginx 32 hex digits - iv estático, útil se você planeja ofuscar profundamente no JavaScript do lado do cliente

testcookie_internal

sintaxe: testcookie_internal (on|off);

padrão: off

contexto: http, server, location

Habilitar verificação de testcookie para redirecionamentos internos (desativado por padrão para fins de otimização!), útil para este tipo de configuração:

rewrite ^/(.*)$ /index.php?$1 last;

testcookie_httponly_flag

sintaxe: testcookie_httponly_flag (on|off);

padrão: off

contexto: http, server, location

Habilitar a flag HttpOnly para o cookie.

testcookie_secure_flag

sintaxe: testcookie_secure_flag (on|off|$variable);

padrão: on

contexto: http, server, location

Habilitar a flag Secure para o cookie. Qualquer valor de variável, exceto "on", é interpretado como Falso.

testcookie_port_in_redirect

sintaxe: testcookie_port_in_redirect (on|off);

padrão: off

contexto: http, server, location

Expor a porta no redirecionamento.

Exemplo de configuração

http {
    #configuração padrão, módulo desabilitado
    testcookie off;

    #definindo o nome do cookie
    testcookie_name BPC;

    #definindo o segredo
    testcookie_secret keepmesecret;

    #definindo a chave da sessão
    testcookie_session $remote_addr;

    #definindo o nome do argumento
    testcookie_arg ckattempt;

    #definindo o número máximo de tentativas de definição de cookie
    testcookie_max_attempts 3;

    #definindo a política p3p
    testcookie_p3p 'CP="CUR ADM OUR NOR STA NID", policyref="/w3c/p3p.xml"';

    #definindo a URL de fallback
    testcookie_fallback http://google.com/cookies.html?backurl=http://$host$request_uri;

    #configurando a lista de permissões
    testcookie_whitelist {
        8.8.8.8/32;
    }

    #definindo redirecionamento via código html
    testcookie_redirect_via_refresh on;

    #habilitar criptografia
    testcookie_refresh_encrypt_cookie on;

    #definindo a chave de criptografia
    testcookie_refresh_encrypt_cookie_key deadbeefdeadbeefdeadbeefdeadbeef;

    #definindo o iv de criptografia
    testcookie_refresh_encrypt_cookie_iv deadbeefdeadbeefdeadbeefdeadbeef;

    #definindo o template de resposta
    testcookie_refresh_template '<html><body>setting cookie...<script type=\"text/javascript\" src=\"/aes.min.js\" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("$testcookie_enc_key"),b=toNumbers("$testcookie_enc_iv"),c=toNumbers("$testcookie_enc_set");document.cookie="BPC="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";location.href="$testcookie_nexturl";</script></body></html>';

    server {
        listen 80;
        server_name test.com;

        location = /aes.min.js {
            gzip  on;
            gzip_min_length 1000;
            gzip_types      text/plain;
            root /var/www/public_html;
        }

        location = /w3c/p3p.xml {
            root /var/www/public_html;
        }

        location / {
            #habilitar módulo para localização específica
            testcookie on;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:80;
        }
    }
}

Veja mais casos no diretório "docs" do projeto.

Conjunto de testes

Este módulo vem com um conjunto de testes baseado em Perl. Graças ao módulo Test::Nginx no mundo Perl.

Fontes

Disponível no github em kyprizel/testcookie-nginx-module.

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório do GitHub para nginx-module-testcookie.