/ TL;DR

SSRF (Server-Side Request Forgery) é uma das falhas mais subestimadas em apps que integram serviços externos. Um único campo "URL da imagem" pode virar leitura de metadados do IMDS na AWS, acesso a bancos internos e escalada dentro da VPC. Guia técnico com 18 vetores.

Server-Side Request Forgery — SSRF — é uma classe de vulnerabilidade que quase nenhum backend "sem HTTP" pensaria ter. O padrão é sempre o mesmo: seu servidor faz uma requisição HTTP na URL que o usuário escolheu, e essa URL aponta para um endereço que só o servidor consegue enxergar.

Em apps modernos rodando em nuvem, o custo de uma SSRF vai de "vazamento de credenciais IAM" a "acesso a bancos e cache internos" em segundos. Este guia mapeia como a falha nasce, os 18 vetores que ainda escapam de bibliotecas populares em 2026, e o que blindar antes de qualquer coisa.

Onde a SSRF nasce

O padrão canônico é qualquer funcionalidade onde o backend puxa um recurso externo baseado em input do usuário:

  • Upload por URL ("cole o link da imagem de perfil")
  • Webhooks configuráveis pelo cliente
  • Preview de link (aquele card do Slack/WhatsApp)
  • Importadores de CSV/XML/JSON remotos
  • Encurtadores de URL
  • Screenshot ou geração de PDF a partir de URL
  • OpenGraph fetch para SEO interno
  • Health checks configuráveis

Em todos, o app faz algo como:

$content = file_get_contents($_POST['url']);

E é aí que o problema começa.

O que atacantes miram

Em vez de uma URL pública, o atacante manda o servidor buscar recursos que só o próprio servidor alcança:

  • AWS/GCP metadata: http://169.254.169.254/latest/meta-data/iam/security-credentials/ retorna credenciais IAM temporárias. Um vazamento aqui costuma ser o pior dia do time de segurança.
  • Localhost: http://127.0.0.1:6379 (Redis), http://127.0.0.1:9200 (Elasticsearch), http://127.0.0.1:15672 (RabbitMQ mgmt). Muitos serviços internos não pedem autenticação porque assumem que só o servidor os enxerga.
  • Redes privadas: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 — outros microserviços da VPC, bancos internos, admin panels.
  • file://: leitura de arquivos locais quando o HTTP client segue esquemas alternativos.

Os 18 vetores que ainda passam

Uma blocklist ingênua ("se começar com http://127, bloqueia") falha por dezenas de razões. Estes são os vetores que ainda passam em produção:

1. IPs em decimal

http://2130706433 = 127.0.0.1. Muitas libs HTTP normalizam antes de checar.

2. IPs em hexadecimal

http://0x7f000001 = 127.0.0.1. Idem.

3. IPs em octal

http://0177.0.0.1 = 127.0.0.1.

4. IPv6 mapeado

http://[::ffff:127.0.0.1] continua chegando em localhost.

5. IPv4 embutido em IPv6

http://[::7f00:1] = mesma coisa.

6. IPv6 abreviado

http://[::1] = localhost em IPv6. Blocklist só de IPv4 falha.

7. DNS rebinding

O atacante controla mal.example.com. Na primeira consulta DNS responde com IP público. Sua checagem passa. Na segunda consulta (feita pelo HTTP client depois), responde com 127.0.0.1. Bingo.

8. Redirect manipulado

Você valida a URL de entrada, mas o HTTP client segue redirects automaticamente. Um Location: http://127.0.0.1 no meio do caminho contorna sua validação.

9. URL parsers divergentes

Em http://[email protected]/, alguns parsers extraem evil.com como host; outros, 127.0.0.1. Se você valida com um parser e faz a request com outro, adivinha.

10. Encoding duplo

http://127.0.0.1http://%31%32%37.%30.%30.%31http://%2531%2532%2537... depende de quantas vezes seu código decodifica.

11. Nomes de host de curl-magic

localtest.me, xip.io, nip.io resolvem para IPs privados sem envolver DNS customizado.

12. Wildcard DNS público

127.0.0.1.nip.io127.0.0.1. Sua blocklist de hostnames não pega.

13. Esquemas alternativos

file://, gopher://, dict://, ldap://. O gopher:// é particularmente perigoso porque permite enviar bytes arbitrários para portas TCP internas.

14. FTP passive redirect

Alguns clients HTTP + FTP fazem bind em portas locais.

15. Cloudflare Tunnel abuse

Um domínio público que via CDN tunela até IP interno.

16. TXT records maliciosos

Alguns integradores fazem lookup de TXT antes do fetch. Ataques via envenenamento de TXT record.

17. IPv6 zone identifier

http://[fe80::1%25eth0] — o %25 é % URL-encoded, o eth0 é um zone identifier que pode fazer chegar em interfaces internas.

18. Header host injection

Você valida a URL mas o proxy interno usa o Host: header para roteamento, e o atacante injeta um Host arbitrário.

Como blindar (de verdade)

Blocklist não é a resposta. Allowlist é.

Passo 1: separe o cliente HTTP. Crie um wrapper único (SafeHttpClient) que TODA request server-side passa. Nada de file_get_contents ou curl_exec espalhados.

Passo 2: resolva DNS antes. Faça o lookup você mesmo, com timeout curto. Cheque o IP resolvido contra uma allowlist de faixas públicas. Só então passe o IP resolvido diretamente ao HTTP client (não o hostname), forçando o Host header a bater.

Passo 3: bloqueie schemes.http e https. Nada de file, gopher, dict, ftp, ldap, data.

Passo 4: siga redirects manualmente. Cada hop passa pela mesma validação, ou o request é abortado.

Passo 5: timeout agressivo. 3 a 5 segundos para conexão + total.

Passo 6: role banido de metadata IMDS. Na AWS, use IMDSv2 obrigatório em toda instância (HttpTokens=required). É o único jeito de eliminar o vetor "SSRF vira credencial IAM" no pior caso.

Como saber se você tem essa falha agora

Duas checagens rápidas para rodar hoje:

  1. Em qualquer endpoint que aceite URL, tente http://169.254.169.254/latest/meta-data/. Se o backend retorna qualquer coisa que pareça metadata, você tem SSRF crítica.
  2. Tente http://127.0.0.1:22. Se o retorno bater na porta SSH (mesmo com erro), o backend está fazendo conexões internas.

Se qualquer uma das duas passar, isso é P0 hoje.

TL;DR para o time

  • SSRF nasce em qualquer feature que faz o servidor buscar recurso externo por URL do usuário.
  • Blocklist perde. Allowlist ganha.
  • Um único wrapper HTTP centralizado é infraestrutura de segurança, não frescura.
  • Se você está na AWS, IMDSv2 obrigatório em toda instância é a segunda linha de defesa contra o vazamento de credenciais.

A varredura da Varredura testa esses 18 vetores automaticamente em todo endpoint que aceita URL — inclusive DNS rebinding e redirect manipulado. Rode uma varredura no seu app para ver quais destes passam hoje.

EV

Equipe Varredura

Time de pesquisa de segurança · Varredura

Sua app em produção passa por essa análise?

Rode uma varredura autônoma em ~60 segundos. Sem cadastro.

Analisar minha aplicação →