flawopen.com/SSRF/SSRF no fetch() do Node.js
O fetch() do Node.js impede SSRF?
Não. O fetch() no servidor faz uma requisição a partir do servidor. Se o chamador escolhe o destino, pode direcionar a requisição a sistemas que o servidor alcança, mas o chamador não. É como pedir a um mensageiro de confiança que entregue um pacote sem conferir o endereço. A exposição depende da rede, identidade, política de URLs e redirects.
providerId, para uma origem configurada pela aplicação. Evita aceitar URLs arbitrárias.Causa raiz: o servidor confia no destino escolhido pelo chamador
O fetch() do Node.js é um cliente HTTP geral, não um mecanismo de política contra SSRF. Ele não decide a quais redes sua aplicação pode se conectar; proteções CORS de navegador não criam essa fronteira no servidor. Analisar a URL também não basta: um host permitido pode resolver para um endereço proibido, e uma resposta pode redirecionar para outro host. Recursos que buscam avatar, webhook, documento ou prévia fornecidos pelo usuário podem criar essa exposição.
Como a requisição cruza a fronteira de confiança
O chamador influencia a URL
Um endpoint aceita uma URL completa ou dados suficientes para construí-la, por exemplo para gerar uma prévia de imagem.
O servidor envia a requisição
O cliente HTTP usa a rota de rede, DNS, proxy e identidade disponíveis ao processo do servidor.
Um redirect pode mudar o destino
Por padrão, Fetch segue redirects. Um destino aprovado inicialmente pode responder com Location para um host que a aplicação deveria bloquear.
A resposta pode expor dados alcançáveis
Se a política e a rede permitirem, serviços internos ou metadados de nuvem podem ser alcançados. Isso depende do ambiente; não ocorre automaticamente em toda chamada.
Padrões Node.js vulnerável e mais seguro
// Não busque uma URL arbitrária fornecida pelo chamador.
const response = await fetch(userProvidedUrl);
// O chamador escolhe uma chave, nunca um destino de rede.
const destinations = new Map([
["status", new URL("https://status.example/")],
["docs", new URL("https://docs.example/")],
]);
const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");
const response = await fetch(target, {
redirect: "error",
signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");
Quando usuários precisam enviar URLs
Prefira aceitar um identificador de provedor e montar a requisição a partir de um mapa fixo de destinos. Se URLs públicas arbitrárias forem essenciais, permita apenas esquemas e portas necessários; rejeite user-info, loopback, IPs privados, link-local e outros destinos IPv4/IPv6 proibidos; valide todos os endereços resolvidos e garanta que a conexão use um endereço validado sem nova resolução não verificada. Desative redirects automáticos ou valide cada salto. Aplique regras independentes de saída de rede, incluindo bloqueios a endpoints de metadados como 169.254.169.254 e o endpoint IPv6 habilitado. Limite tempo de conexão, tamanho da resposta e concorrência; não encaminhe credenciais internas ao host buscado.
Checklist de prevenção de SSRF
- ✓Sempre que possível, substitua URLs arbitrárias por um mapa fixo entre uma chave de provedor validada e um destino controlado pela aplicação.
- ✓Exija
https:e portas esperadas; rejeite credenciais na URL, hosts inesperados, IPs literais e faixas proibidas. - ✓Desative redirects com
redirect: "error"; se forem necessários, valide cada destino antes de conectar. - ✓Evite DNS rebinding validando todas as respostas A/AAAA e vinculando a conexão a um endereço validado, sem perder a verificação do nome. Aplique também a retries e proxies.
- ✓Aplique firewall ou proxy de saída para bloquear loopback, redes privadas, link-local e metadados, inclusive IPv6. Não dependa só da validação na aplicação.
- ✓Defina limites de tempo, bytes de resposta e concorrência; não encaminhe cookies, cabeçalhos de autorização nem credenciais de nuvem ao destino.
- ✓Na AWS, exija IMDSv2 e restrinja o acesso aos metadados como defesa em profundidade; isso não substitui validação de URL nem controles de saída.
Perguntas frequentes
Não. Redirects, formas alternativas de IPv4/IPv6, DNS rebinding, proxies e corridas entre resolução e conexão podem contornar uma verificação simples. Prefira uma lista de destinos permitidos. Se destinos arbitrários forem necessários, valide cada endereço resolvido e faça a conexão usar esse resultado; aplique a mesma regra na saída de rede.
Não. IMDSv2 exige um fluxo com token e reduz algumas exposições, mas SSRF ainda pode atingir outros serviços internos ou endpoints de metadados sob outras configurações. Mantenha controles de destino e de saída.
Fontes primárias
- OWASP — prevenção de SSRF
- Node.js — API global fetch
- Padrão WHATWG Fetch — modo de redirect
- AWS — opções do serviço de metadados EC2
- CWE-918 — Server-Side Request Forgery