
Scanner de configuração estática que sinaliza configurações do nginx vulneráveis ao bug complex_value de two-pass capture-clobbering (regex map + regex capture → heap overflow / info leak).
Um scanner estático somente leitura que sinaliza configurações nginx vulneráveis à classe de bug de captura-clobber em duas passagens complex_value (aviso do F5/nginx SIRT, julho de 2026). Ele analisa sua configuração e relata o padrão vulnerável com o motivo e a localização. Ele não explora nada e não toca no servidor em execução.
Arquivo único, apenas biblioteca padrão, Python 3.6+.
Análise completa da vulnerabilidade: https://cyberstan.co.uk/nginx-rce/
O nginx constrói muitos valores de diretivas em duas passagens. Uma passagem LEN mede o comprimento e aloca um buffer, depois uma passagem VALUE escreve nele. Capturas de regex ($1 a $9, ou nomeadas (?P<name>...)) são lidas de um estado compartilhado por requisição. Um map cuja chave de correspondência é uma expressão regular executa uma nova correspondência PCRE no momento em que sua variável é avaliada, e essa correspondência sobrescreve o estado de captura compartilhado. Se uma captura é medida na passagem LEN e então um map de regex é executado antes que a passagem VALUE reescreva essa captura, as duas passagens divergem:
Ambas as direções são acionáveis remotamente quando a entrada do map é
influenciada pelo atacante ($request_body, $http_*, $arg_*, $uri,
$ssl_preread_server_name, e assim por diante).
O scanner sinaliza uma location ou server quando todos estes elementos caem em um único buffer de duas passagens, na ordem explorável:
location ~ de regex, server_name ~, rewrite,
if (... ~ ...), ou um map de regex com um grupo de captura.map (http ou stream) com uma chave de correspondência
de regex ~ ou ~*, referenciado por sua variável de saída.return, set, add_header, proxy_method,
proxy_pass, rewrite, index, e outras): ambas as referências no mesmo valor.proxy_set_header, proxy_set_body,
fastcgi_param, scgi_param, uwsgi_param, grpc_set_header): estas
constroem um buffer por requisição para toda a família, então as duas referências podem
estar em diretivas separadas na mesma location.# scan a single config (follows include directives by default)
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf
# scan a directory (uses nginx.conf if present, else all *.conf)
python3 nginx_capture_clobber_scan.py /etc/nginx/
# scan several roots
python3 nginx_capture_clobber_scan.py site-a.conf site-b.conf
# machine-readable output
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --json
# do not expand include directives
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf --no-includes
| Opção | Efeito |
|---|---|
--json | Emite um relatório JSON em vez de texto. |
--no-includes | Não segue as diretivas include. |
| Código | Significado |
|---|---|
0 | Nenhuma configuração vulnerável encontrada. |
1 | Pelo menos uma configuração vulnerável encontrada. |
2 | Erro de uso (nenhum caminho fornecido ou nenhum encontrado). |
Utilizável em CI, pois uma configuração vulnerável retorna código de saída diferente de zero:
python3 nginx_capture_clobber_scan.py /etc/nginx/nginx.conf || echo "review needed"
O modo texto imprime, para cada achado: arquivo e linha, o escopo envolvente, a diretiva sink, as variáveis de captura e de mapa envolvidas, o mapa que disparou e um motivo em uma linha. Uma seção liberada lista coexistências de ordem segura. --json produz:
{
"vulnerable": true,
"findings": [
{
"file": "/etc/nginx/conf.d/api.conf",
"line": 12,
"scope": "location ~ ^/api/(.+)$",
"directive": "proxy (family buffer)",
"captures": ["$1"],
"map_vars": ["$is_bot"],
"triggers": ["$is_bot <- regex-map on $http_user_agent [nginx.conf:30]"],
"reason": "..."
}
],
"cleared_safe_order": [],
"regex_maps": [],
"missing_includes": []
}
map de regex no mesmo local ou buffer que uma
referência $1 a $9 ou de captura nomeada.(?P<name>...) em múltiplos maps de regex.proxy_set_header ou
fastcgi_param.set.include ilegíveis (por exemplo, caminhos absolutos que não existem
localmente) são reportados em missing_includes, não ignorados silenciosamente. Execute-o
no host onde a configuração é resolvida para cobertura completa.Análise da vulnerabilidade e cadeia de exploração: https://cyberstan.co.uk/nginx-rce/