
NGINX Rift: Como IA Autônoma Achou Bug de RCE de 18 Anos
Um heap buffer overflow de 18 anos no NGINX foi descoberto por uma IA autônoma em 6 horas. Analisamos a engine de script e o fluxo do exploit.
✨TL;DR / Sumário Executivo
Um heap buffer overflow de 18 anos no NGINX foi descoberto por uma IA autônoma em 6 horas. Analisamos a engine de script e o fluxo do exploit.
💡 TL;DR (Too Long; Didn't Read)
Principais conclusões em 90 segundos:
- A Vulnerabilidade: Rastreada como CVE-2026-42945 (CVSS 9.2), o NGINX Rift é um heap buffer overflow crítico no
ngx_http_rewrite_moduleque pode levar a Negação de Serviço (DoS) ou Execução Remota de Código (RCE).- O Tempo de Vida: A vulnerabilidade existia sem detecção no núcleo do NGINX desde 2008, sobrevivendo a 18 anos de revisões manuais de código, auditorias de segurança e análise estática automatizada.
- A Inflexão da IA: Um agente autônomo de IA desenvolvido pela DepthFirst descobriu o bug em apenas 6 horas, marcando uma mudança monumental na descoberta automatizada de vulnerabilidades.
- Causa Raiz Técnica: Uma incompatibilidade de estado na engine de script do NGINX. A engine calcula o tamanho do buffer de destino durante uma "passagem de comprimento" (length pass) usando um conjunto de premissas, mas realiza a cópia de string real em uma "passagem de cópia" (copy pass) usando regras de escape mais agressivas, causando uma escrita heap fora dos limites.
- Padrão Vulnerável: Escopos onde uma diretiva
rewritecontendo uma query string (?) é imediatamente seguida por uma diretivarewrite,ifousetque referencia grupos de captura PCRE sem nome (como$1,$2).- Mitigação: Atualize imediatamente (NGINX Open Source 1.30.1 / 1.31.0 ou NGINX Plus R36 P4 / R35 P2 / R32 P6). Se a atualização for adiada, converta as capturas PCRE sem nome em grupos de captura nomeados (por exemplo,
(?<name>)), o que desvia a execução da lógica defeituosa do compilador de script.
1. Introdução: A Mudança Decisiva na Caça a Vulnerabilidades
Por décadas, a postura de segurança das infraestruturas de código aberto baseou-se na premissa da Lei de Linus: "com olhos suficientes, todos os bugs são rasos". Componentes críticos de sistemas — como OpenSSL, o kernel do Linux e o NGINX — têm sido submetidos a um escrutínio intenso. Eles são compilados com alertas agressivos do compilador, escaneados com suítes comerciais de SAST (teste estático de segurança de aplicação) e testados continuamente via frameworks de fuzzing.
No entanto, em 13 de maio de 2026, a empresa de pesquisa de segurança DepthFirst anunciou a CVE-2026-42945, coloquialmente chamada de NGINX Rift. O NGINX Rift é um heap buffer overflow crítico na engine de script do NGINX, alcançando uma pontuação CVSS v4.0 de 9.2. Ele permite que um invasor não autenticado trave processos worker do NGINX ou, sob condições específicas de layout de memória, obtenha execução remota de código (RCE) arbitrária.
O aspecto mais alarmante do NGINX Rift não é sua gravidade, mas sua origem e ciclo de vida. A vulnerabilidade foi introduzida na base de código do NGINX em 2008. Por dezoito anos, ela permaneceu à vista de todos, ativa em cerca de um terço dos servidores web do mundo. Sobreviveu à transição do NGINX de um servidor web de nicho russo para a espinha dorsal de infraestrutura dominante do SaaS moderno, resistindo a todos os scanners automatizados do mercado.
Ela foi finalmente descoberta não por um engenheiro de sistemas humano ou por um scanner estático sofisticado, mas por um agente autônomo de IA. Rodando em um loop fechado com acesso à árvore de fontes do NGINX, o agente identificou a complexa incompatibilidade lógica, sintetizou uma configuração vulnerável do NGINX e produziu um payload de teste (PoC) funcional em menos de seis horas.
Isso representa um ponto de inflexão. A premissa defensiva de que códigos em C legados e altamente auditados são inerentemente mais seguros do que códigos mais novos foi quebrada. Quando agentes de IA conseguem analisar bases de código em velocidade de máquina, localizar falhas em máquinas de estado e mapear caminhos de exploit automaticamente, o cenário de segurança muda de um ciclo lento governado por humanos para uma corrida algorítmica veloz.
Para se defender dessa nova realidade, engenheiros Staff+ e arquitetos de sistemas precisam entender a física da vulnerabilidade NGINX Rift: como o compilador de script compila diretivas, por que ocorre a falha de alocação de memória em C, quais configurações disparam o bug e como implementar mitigações imediatas.
2. Por Baixo do Capô: A Arquitetura da Engine de Script do NGINX
Para compreender como o NGINX Rift ocorre, precisamos primeiro examinar a arquitetura do parser de configuração do NGINX e sua "engine de script" interna.
Diferente de servidores web simples que interpretam configurações em pares planos de chave-valor, o NGINX compila blocos de configuração complexos — particularmente aqueles dentro do ngx_http_rewrite_module — em uma representação proprietária de bytecode durante a inicialização. Diretivas como rewrite, if e set não são executadas como strings puras ou simples buscas condicionais. Em vez disso, o NGINX as compila em um array sequencial de instruções de script executáveis.
Quando o NGINX compila um bloco de configuração contendo regras de reescrita, ele gera uma série de ponteiros de função (ngx_http_script_code_pt) que apontam para rotinas do sistema. Em tempo de execução, quando uma requisição HTTP atinge um bloco de localização governado por esses scripts, a engine de script do NGINX executa as instruções compiladas sequencialmente.
Para maximizar a performance e evitar a fragmentação do heap, o NGINX evita concatenações dinâmicas de string que exijam realocações frequentes. Ao concatenar variáveis, aplicar expressões regulares ou reescrever URIs, o NGINX executa a engine de script em duas passagens distintas:
- A Passagem de Cálculo de Comprimento (
ngx_http_script_run_pt): A engine de script itera por todas as variáveis e elementos estáticos que comporão a string de saída final. Ela consulta cada elemento para determinar seu tamanho exato em bytes no formato serializado final. A engine soma esses valores para calcular o tamanho absoluto do buffer de destino. - A Passagem de Alocação de Memória e Cópia: O NGINX aloca um bloco único e contíguo de memória do pool de memória da conexão (
ngx_pool_t) correspondente ao tamanho exato calculado na passagem de comprimento. Em seguida, ele executa a engine de script uma segunda vez. Desta vez, a engine copia os caracteres de cada componente diretamente no buffer recém-alocado, avançando um ponteiro de destino (u_char *) conforme escreve.
Esse sistema de duas passagens é um padrão elegante de gerenciamento de memória em C. Ele garante vazamento zero de memória, minimiza o overhead de alocação e descarta a necessidade de realocações dinâmicas. No entanto, esse padrão depende de um invariante crítico: a passagem de cálculo de comprimento e a passagem de cópia devem fazer premissas idênticas sobre o tamanho final dos dados.
Se a passagem de comprimento calcular que uma variável consumirá 10 bytes, mas a passagem de cópia escrever 15 bytes porque formata ou escapa os dados de maneira diferente, o ponteiro de destino escreverá além do buffer alocado. Em um programa C, isso resulta em uma gravação fora dos limites (out-of-bounds write), corrompendo estruturas de heap adjacentes no processo worker do NGINX. Esse é exatamente o invariante que a CVE-2026-42945 viola.
3. Mecânica do Exploit: O Descompasso de Tamanho no ngx_http_rewrite_module
A essência da vulnerabilidade NGINX Rift está em como a engine de script lida com capturas de expressões regulares ao lado de strings de reescrita contendo parâmetros de consulta (query parameters).
Ao escrever uma expressão regular no NGINX, como:
rewrite ^/users/(.*)$ /profile?id=$1 last;O compilador do NGINX registra o destino da reescrita /profile?id=$1 como um script complexo. Ele compila esse script em uma sequência de instruções:
- Um segmento de string estática
/profile?id= - Um código de captura de variável representando
$1
Em tempo de execução, quando uma requisição chega, a engine de script avalia a expressão regular contra a URI da requisição. Ela armazena a substring capturada (ex: 12345 de /users/12345) em um contexto de correspondência.
Ao executar a passagem de comprimento para a reescrita, o NGINX avalia o tamanho do prefixo estático, o separador de query ? e a string capturada. No entanto, como essa reescrita modifica a query string da requisição, o NGINX deve lidar com o escape de URL.
Para evitar ataques de injeção e garantir que a URI reescrita seja compatível com a especificação RFC de HTTP, o NGINX precisa escapar certos caracteres na variável capturada (como espaços, colchetes ou caracteres de controle) antes de gravá-los na query string. Por exemplo, um espaço deve ser reescrito como %20, transformando uma entrada de 1 caractere em uma saída de 3 caracteres.
Entrada: "/users/admin data"
$1: "admin data" (10 caracteres)
Escapado: "admin%20data" (12 caracteres)A passagem de comprimento deve, portanto, antecipar esse escape e adicionar os bytes extras ao tamanho total de alocação do buffer. No código-fonte do NGINX, essa lógica é tratada calculando a quantidade de caracteres que precisam de escape e somando 2 * escape_count ao total do comprimento.
Contudo, a engine de script do NGINX possui outra camada de otimização. Se uma diretiva de reescrita não modifica a query string (ou seja, não há um ? no destino), o NGINX não precisa escapar as capturas da mesma forma, porque a captura será tratada como parte do caminho, que tem restrições de escape diferentes.
A vulnerabilidade surge devido a um bug de rastreamento de estado no compilador de variáveis da engine de script. Ao compilar múltiplas diretivas no mesmo contexto, o NGINX rastreia se o script ativo está operando dentro de um "contexto de query string" usando uma flag booleana no estado do compilador: sc->zero.
Se um bloco de configuração contém uma diretiva de reescrita com query string:
rewrite ^/source/(.*)$ /dest?param=$1;O compilador define a flag de estado de query string. O calculador de comprimento da engine observa essa flag e adiciona corretamente o overhead de escape ao comprimento calculado para $1.
Contudo, se essa diretiva for seguida por outra diretiva no mesmo bloco de localização que também referencia variáveis de captura (como uma condição if ou uma diretiva set):
set $var $2;O compilador reutiliza o contexto de compilação. Sob condições específicas de sequência, a flag de estado de query (sc->zero) não é redefinida corretamente ou fica dessincronizada entre o manipulador de cálculo de comprimento e o manipulador de cópia.
Como resultado, durante a execução:
- Passagem de Comprimento: O código de cálculo de comprimento da segunda diretiva avalia
$2. Devido à flag de estado desatualizada, assume que a variável não precisa de escape de query string ou calcula o comprimento usando o tamanho padrão da string sem escape (ex: 10 bytes). - Alocação: O NGINX aloca um buffer baseado nesse comprimento sem escape (10 bytes).
- Passagem de Cópia: O manipulador de cópia da captura da variável é executado. Como outro caminho de código avalia o estado da requisição, o manipulador de cópia detecta que está processando uma requisição que possui a flag de query string ativa no nível da requisição. Ele aplica a lógica completa de escape de query string, transformando caracteres especiais (ex: espaços em
%20) e gravando a string escapada no buffer. - Estouro (Overflow): O manipulador de cópia grava a string escapada (12 bytes) no buffer alocado (10 bytes). O ponteiro escreve 2 bytes fora dos limites, corrompendo a memória adjacente no heap.
Se um invasor controla o valor do grupo de captura (o que ocorre, pois ele é extraído diretamente da URI da requisição), ele pode moldar uma URI contendo muitos caracteres que requerem escape. Ao enviar uma requisição com 100 espaços, ele pode fazer com que a passagem de comprimento aloque um buffer que é 200 bytes menor do que o necessário, permitindo-lhe sobrescrever 200 bytes do heap adjacente com a string %20 ou outras sequências escapadas.
4. O Padrão de Configuração Vulnerável
Para acionar a CVE-2026-42945, o NGINX deve estar rodando uma configuração que compila múltiplas diretivas referenciando capturas de expressão regular sem nome em uma sequência na qual o estado do contexto é compartilhado.
O padrão genérico vulnerável envolve uma diretiva rewrite que introduz um parâmetro de consulta, imediatamente seguida por outra diretiva de configuração (como set, if ou outro rewrite) que referencia variáveis de captura PCRE sem nome (como $1, $2) dentro do mesmo escopo.
Considere este padrão de configuração comum em muitos proxies reversos e API gateways:
# Exemplo de Configuracao NGINX Vulneravel
server {
listen 8080;
server_name api.example.internal;
location /legacy-api {
# Diretiva 1: Rewrite que introduz um parametro de query e captura a entrada
rewrite ^/legacy-api/(.*)$ /v2/endpoint?source=legacy&query=$1;
# Diretiva 2: Atribuicao imediata referenciando um grupo de captura sem nome
# Esta atribuicao reutiliza o contexto de compilacao, disparando a falha de estado
set $extracted_payload $1;
proxy_pass http://backend_upstream;
}
}Nesta configuração:
- A diretiva
rewritecorresponde a qualquer caminho de requisição iniciado com/legacy-api/e captura o restante em$1. O destino contém uma query string (?source=legacy&query=$1). - Imediatamente depois, a diretiva
settenta atribuir o valor da captura$1a uma variável personalizada$extracted_payload. - Como essas diretivas estão no mesmo bloco, o compilador do NGINX as compila em um único array de script. O estado do contexto de query string é corrompido entre as duas instruções.
Se um cliente envia a seguinte requisição:
GET /legacy-api/busca%20termo%20com%20espacos HTTP/1.1
Host: api.example.internalA regex captura busca termo com espacos (contendo 3 espaços).
- Durante a passagem de cálculo de comprimento para a diretiva
set, o NGINX avalia o comprimento da string bruta:24caracteres. Ele aloca24bytes. - Durante a passagem de cópia, a engine aplica o escape de query nos espaços, transformando a string em
busca%20termo%20com%20espacos(que tem30caracteres). - A engine copia
30bytes no buffer de24bytes, resultando em um heap overflow de 6 bytes.
Se o invasor aumentar a quantidade de espaços ou caracteres de controle na URI, ele poderá dimensionar o tamanho do estouro conforme desejado.
5. A História da Descoberta por IA: Como o Bug Foi Encontrado
A descoberta do NGINX Rift pelo agente autônomo de IA da DepthFirst é um caso de estudo sobre como os agentes baseados em LLM estão redefinindo a pesquisa de segurança.
Analisadores estáticos tradicionais de código (SAST) funcionam buscando assinaturas conhecidas ou construindo árvores de sintaxe abstrata (ASTs) para rastrear o fluxo de dados (análise de fluxo de dados corrompidos/taint analysis). Embora o SAST seja excelente para localizar buffer overflows simples (como um strcpy direto ou um memcpy sem validação de tamanho), ele tem dificuldades com inconsistências lógicas em máquinas de estado complexas.
No caso do NGINX, o código da passagem de comprimento e o da passagem de cópia residem em funções diferentes dentro de src/http/ngx_http_script.c:
ngx_http_script_copy_var_len_code(passagem de comprimento)ngx_http_script_copy_var_code(passagem de cópia)
Como ambas as funções são sintaticamente corretas, contêm verificações de limites e usam as primitivas de memória segura do NGINX, um scanner estático não vê problemas. A vulnerabilidade é puramente semântica: as duas funções são executadas em momentos diferentes, compartilhando um estado compilado que pode divergir sob sequências específicas de diretivas.
+-----------------------------------------------------------------------+
| Loop de Agente de IA Autonomo |
+-----------------------------------------------------------------------+
│
▼
+─────────────────────────────+
│ Analise de Codigo Semantica│
│ (Le o codigo da engine) │
+─────────────────────────────+
│
▼
+─────────────────────────────+
│ Hipotetiza Falha de Logica │
│ (Passagem len vs pass copia)│
+─────────────────────────────+
│
▼
+─────────────────────────────+
│ Gera Configuracoes NGINX │
│ (Para forcar estado comp.) │
+─────────────────────────────+
│
▼
+─────────────────────────────+
│ Fuzza Build NGINX Local │
│ (Envia URIs com espacos) │
+─────────────────────────────+
│
▼
+─────────────────────────────+
│ Detecta Crash de Heap │
│ (Confirma CVE-2026-42945) │
+─────────────────────────────+O agente da DepthFirst contornou as limitações dos scanners estáticos rodando um ciclo de feedback ativo e fechado:
- Análise Semântica: O agente leu o código-fonte da engine de script do NGINX. Ele notou que a cópia de strings depende de um comprimento pré-calculado e começou a procurar por qualquer caminho de código onde a lógica de cálculo de comprimento diferisse da lógica de cópia.
- Geração de Hipóteses: Ele identificou que variáveis e capturas são processadas usando flags do compilador (
sc->zero) para rastrear contextos de query string. Ele hipotetizou que se uma configuração compilasse múltiplas diretivas referenciando variáveis em sequência, essa flag poderia se tornar desatualizada ou incompatível. - Síntese de Ambiente de Testes: O agente gerou uma série de arquivos de configuração do NGINX contendo diferentes permutações das diretivas
rewrite,seteif. - Execução Local e Fuzzing: O agente compilou o NGINX localmente com o AddressSanitizer (ASan) ativado. Ele iniciou o processo NGINX usando as configurações geradas e escreveu um script em Python para enviar requisições HTTP com vários níveis de escape de caracteres especiais.
- Análise do Crash: Quando enviou uma requisição contendo espaços para um bloco de localização com o padrão
rewrite ...; set ...;, o ASan sinalizou um crash de heap-buffer-overflow. O agente analisou o rastreamento de pilha do ASan, confirmou que o estouro ocorria emngx_http_script_copy_var_codee validou o bug.
Em seis horas a partir do início de sua execução no código, o agente gerou um relatório de vulnerabilidade completo, uma configuração mínima reproduzível do NGINX e o payload de requisição HTTP necessário para acionar o travamento.
Esta descoberta destaca uma mudança significativa: os agentes de IA não estão mais limitados a encontrar bugs simples em funções isoladas. Ao gerar configurações, compilar software, analisar comportamentos em tempo de execução e ajustar payloads de teste dinamicamente, eles conseguem localizar falhas arquiteturais complexas que escaparam aos olhos humanos por quase duas décadas.
6. Correção: Patches e Contornos de Configuração
Se a sua infraestrutura roda o NGINX, você deve auditar suas configurações e aplicar mitigações imediatamente.
A Correção Definitiva: Atualizando o NGINX
A solução mais segura é atualizar o NGINX para uma versão onde o estado do contexto do compilador de script seja devidamente redefinido e sincronizado entre as passagens.
- NGINX Open Source: Atualize para 1.30.1 ou 1.31.0 (dependendo de estar no ramo estável ou mainline).
- NGINX Plus: Aplique as versões de patch R36 P4, R35 P2 ou R32 P6.
Esses patches modificam src/http/ngx_http_script.c para garantir que as flags de contexto do compilador sejam limpas explicitamente e reavaliadas para cada instrução de script, evitando que flags de estado desatualizadas vazem entre as diretivas compiladas.
A Mitigação Imediata: Grupos de Captura Nomeados
Se você não puder atualizar suas instâncias do NGINX imediatamente devido a janelas de manutenção ou restrições de controle de mudança, poderá mitigar a vulnerabilidade inteiramente por meio de alterações na configuração.
A vulnerabilidade requer que a engine de script referencie grupos de captura sem nome (como $1, $2), que dependem de indexação posicional e registradores compartilhados do contexto do compilador. Se você reescrever suas expressões regulares para usar grupos de captura nomeados, o NGINX compilará as variáveis usando um caminho de código diferente (ngx_http_script_add_var_code) que não compartilha o registrador posicional com bug.
Veja como transformar uma configuração vulnerável em uma segura:
# Configuracao NGINX SEGURA / MITIGADA
server {
listen 8080;
server_name api.example.internal;
location /legacy-api {
# Padrao vulneravel substituido por um grupo de captura nomeado (?<id>)
rewrite ^/legacy-api/(?<id>.*)$ /v2/endpoint?source=legacy&query=$id;
# Atribuicao segura referenciando a variavel nomeada $id
# Isso usa ngx_http_script_add_var_code, contornando o erro de buffer
set $extracted_payload $id;
proxy_pass http://backend_upstream;
}
}Ao mudar (.*) para (?<id>.*) e referenciar $id em vez de $1, você força o NGINX a resolver a variável pelo nome em tempo de execução. As passagens de comprimento e cópia para variáveis nomeadas não compartilham o estado posicional com bug, eliminando a incompatibilidade de cálculo e impedindo o heap buffer overflow.
7. Lições Estratégicas: Segurança de Software na Era Agêntica
O evento NGINX Rift traz várias lições estratégicas para engenheiros Staff+, diretores de segurança e arquitetos de sistemas.
1. Reavalie o Risco de Bases de Código "Hardened"
Muitas vezes assumimos que bases de código antigas e amplamente utilizadas são seguras porque resistiram ao teste do tempo. Esse é um viés cognitivo. O fato de um bug ter existido no NGINX desde 2008 demonstra que vulnerabilidades críticas podem se esconder à vista de todos indefinidamente.
Ao conduzir avaliações de fornecedores ou auditar a infraestrutura interna, não trate a idade ou a popularidade de uma dependência como sinônimo de segurança. Implemente isolamentos defensivos (como sandboxing de containers, AppArmor ou SELinux) em torno de todos os serviços em C/C++ expostos publicamente, independentemente de quão "maduros" eles sejam.
2. Prepare-se para a Descoberta de Vulnerabilidades Assimétrica
O custo para encontrar vulnerabilidades está despencando. Historicamente, encontrar um bug como o NGINX Rift exigia que um pesquisador de segurança especializado passasse semanas fazendo engenharia reversa em máquinas de estado. Agora, um agente autônomo de IA consegue realizar a mesma análise por alguns dólares de custo computacional.
Essa assimetria significa que o volume de divulgações de vulnerabilidades de dia zero (zero-day) deve aumentar significativamente. As organizações precisam migrar de ciclos reativos de correção (onde atualizações são agendadas com semanas de antecedência) para esteiras de deploy rápido e automatizado, capazes de aplicar patches ou contornos de configuração em poucas horas após a divulgação.
3. Implemente Auditorias de Configuração
Como o NGINX Rift é ativado por um padrão de configuração específico, você deve rodar varreduras automáticas em seus arquivos nginx.conf ativos. Use padrões simples de grep ou analisadores de configuração baseados em AST para detectar qualquer ocorrência em que uma diretiva rewrite contendo um ? seja seguida por atribuições de variáveis referenciando grupos de captura sem nome ($1, $2, etc.) no mesmo bloco. Estabeleça o uso de grupos de captura nomeados no guia de estilo de sua organização.
Ao tratar configurações como código e aplicar o mesmo rigor de linting, testes e análise estática que você aplica ao código da aplicação, você conseguirá identificar e mitigar padrões vulneráveis antes que cheguem à produção.
Fontes Externas
- NGINX Rift: Achieving Remote Code Execution via an 18-Year-Old Vulnerability — DepthFirst Research
- Proof-of-Concept Exploit for CVE-2026-42945 — DepthFirst GitHub Disclosures
- F5 Security Advisory: NGINX Open Source and NGINX Plus Heap Buffer Overflow CVE-2026-42945
- Critical NGINX Vulnerability Analysis — Akamai Security Research
- AlmaLinux OS Security Advisory: NGINX Rift Mitigations
Leituras Relacionadas no gsstk
- Esta Semana o Kernel Ficou Interessante Novamente — analisando tendências emergentes de segurança de baixo nível e linkers
- A Ressaca do Capex: Quando a Aposta de US$ 725Bi de 2026 Encontra a Parede de Depreciação de 2028 — a infraestrutura e a economia de capital impulsionando as alocações de segurança dos hyperscalers
- Stacks de IA Soberana — Por Que Três Continentes Pararam de Compartilhar em 2026 — como fronteiras geográficas e regulatórias estão remodelando a engenharia de sistemas
Este artigo foi estruturado por humanos e sintetizado com auxílio de inteligência artificial sob a persona Aether (AI).