Server-Side Request Forgery (SSRF)
1. O que é SSRF e por que importa para Devs
1.1. Definição
Server-Side Request Forgery (SSRF) é uma vulnerabilidade onde um servidor web faz requisições não intencionais para recursos internos ou externos com base em entrada fornecida pelo usuário. O ataque explora a confiança que o servidor tem em si mesmo para acessar sistemas que normalmente seriam inacessíveis ao atacante.
1.2. Impactos
- Acesso a redes internas e serviços privados
- Leitura de metadados de instâncias cloud (AWS, GCP, Azure)
- Bypass de firewalls e controles de acesso
- Execução de comandos em serviços internos (Redis, Memcached)
- Exfiltração de dados sensíveis
1.3. SSRF básico vs. cego (blind SSRF)
No SSRF básico, o atacante recebe resposta direta do servidor alvo (ex: conteúdo de um arquivo interno). No blind SSRF, o atacante não vê a resposta, mas pode inferir sucesso por meio de side-channels como tempo de resposta, logs ou callbacks externos.
2. Como SSRF funciona na prática
2.1. Fluxo típico de ataque
Usuário → Envia URL maliciosa → Servidor processa → Servidor faz requisição interna → Dado vaza
2.2. Exemplos de funcionalidades vulneráveis
- Webhooks: servidor envia POST para URL fornecida pelo usuário
- Importadores de URL: ferramentas que baixam conteúdo de URLs
- Proxies: servidores que buscam recursos em nome do cliente
- Validadores de URL: serviços que verificam se um link está ativo
2.3. Cenário real: ataque a metadados AWS
# Exemplo de URL maliciosa para acessar metadados AWS
http://169.254.169.254/latest/meta-data/
# O servidor vulnerável faz GET para essa URL e retorna dados sensíveis
# Como chaves de acesso, ID da instância, etc.
3. Técnicas de exploração comuns
3.1. Bypass de validação de URL
# Redirecionamento
http://legitimo.com/redirect?url=http://169.254.169.254/
# Encoding de IP
http://0x7f000001/ # 127.0.0.1 em hex
http://2130706433/ # 127.0.0.1 em decimal
# Variações de DNS
http://localhost/
http://127.1/
http://0/
3.2. Uso de protocolos alternativos
# Protocolo file:// para ler arquivos locais
file:///etc/passwd
# Protocolo gopher:// para interagir com serviços TCP
gopher://redis:6379/_SET%20key%20value
# Protocolo dict:// para consultar serviços
dict://localhost:6379/info
3.3. Exploração de serviços internos
# Redis - injeção de comandos
gopher://localhost:6379/_SET%20mykey%20"malicious"%0D%0A
# Memcached - armazenamento de payload
http://localhost:11211/set%20key%200%200%205%0D%0Ahello
# Bancos de dados - consulta via HTTP
http://db.internal:5432/
4. Estratégias de prevenção: validação e sanitização
4.1. Whitelist de domínios e IPs permitidos (nunca blacklist)
# Exemplo de whitelist em Python
ALLOWED_DOMAINS = ["api.trusted.com", "cdn.trusted.com"]
ALLOWED_IPS = ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
def is_allowed(url):
parsed = urlparse(url)
hostname = parsed.hostname
ip = socket.gethostbyname(hostname)
if hostname not in ALLOWED_DOMAINS:
return False
if not is_private_ip(ip):
return False
return True
4.2. Validação rigorosa de esquemas (apenas https://) e parsing de URL
# Validação de esquema em Node.js
function validateURL(url) {
const parsed = new URL(url);
if (parsed.protocol !== 'https:') {
throw new Error('Apenas HTTPS permitido');
}
if (parsed.hostname.includes('.')) {
// Verifica se é um domínio válido
}
return parsed;
}
4.3. Bloqueio de resolução de DNS para IPs privados
# Exemplo em Python com verificação de IP privado
import ipaddress
def is_private_ip(ip_string):
ip = ipaddress.ip_address(ip_string)
return ip.is_private or ip.is_loopback or ip.is_link_local
def safe_request(url):
parsed = urlparse(url)
ip = socket.gethostbyname(parsed.hostname)
if is_private_ip(ip):
raise Exception("Acesso a IP privado bloqueado")
return requests.get(url, timeout=5)
5. Defesas no nível de rede e infraestrutura
5.1. Isolamento de rede: VPC, sub-redes privadas, grupos de segurança
- Servidores de aplicação em sub-redes privadas
- Acesso a banco de dados apenas via IPs internos
- Grupos de segurança que bloqueiam tráfego de saída não autorizado
5.2. Firewall de saída (egress filtering) e proxies reversos
# Regras de firewall de saída (exemplo iptables)
-A OUTPUT -d 10.0.0.0/8 -j DROP
-A OUTPUT -d 172.16.0.0/12 -j DROP
-A OUTPUT -d 192.168.0.0/16 -j DROP
-A OUTPUT -d 169.254.169.254 -j DROP
-A OUTPUT -p tcp --dport 6379 -j DROP # Redis
5.3. Uso de serviços de metadados protegidos (IMDSv2 no AWS)
# IMDSv2 requer token de sessão
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/
6. Boas práticas de codificação para evitar SSRF
6.1. Nunca confiar em URLs fornecidas pelo usuário para requisições diretas
# ERRADO - direto da entrada do usuário
url = request.GET.get('url')
response = requests.get(url)
# CORRETO - usar whitelist e validação
url = request.GET.get('url')
if not is_allowed(url):
return error_response()
response = safe_request(url)
6.2. Implementar timeouts e limites de redirecionamento
# Timeout e limite de redirecionamentos em Python
response = requests.get(
url,
timeout=5, # Timeout total
allow_redirects=True,
max_redirects=5 # Máximo de redirecionamentos
)
6.3. Desabilitar redirecionamentos automáticos e protocolos perigosos
# Desabilitar redirecionamentos em Node.js com axios
const response = await axios.get(url, {
maxRedirects: 0,
timeout: 5000,
validateStatus: function (status) {
return status >= 200 && status < 300;
}
});
7. Testes e detecção de SSRF
7.1. Ferramentas de teste
- Burp Suite: plugin Collaborator para detectar blind SSRF
- SSRFmap: ferramenta automatizada para exploração
- Interactsh: servidor de callback para detectar requisições externas
# Exemplo de teste manual com curl
curl -v "http://vulnerable.com/fetch?url=http://169.254.169.254/latest/meta-data/"
# Teste com callback externo
curl "http://vulnerable.com/fetch?url=http://YOUR_INTERACTSH.oastify.com/test"
7.2. Monitoramento de logs: requisições inesperadas para IPs internos
# Logs a monitorar (exemplo de padrão)
GET /latest/meta-data/ # Tentativa de SSRF em cloud
Connection to 127.0.0.1:6379 # Conexão inesperada com Redis
DNS query for internal.trusted.com # Resolução de DNS suspeita
7.3. Checklist de revisão de código para identificar pontos cegos
- [ ] Todas as URLs de entrada passam por whitelist?
- [ ] Esquemas são validados (apenas HTTPS)?
- [ ] Redirecionamentos são limitados?
- [ ] Timeouts estão configurados?
- [ ] IPs privados são bloqueados?
- [ ] Protocolos perigosos (file://, gopher://) estão desabilitados?
- [ ] Metadados cloud estão protegidos (IMDSv2)?
- [ ] Firewall de saída está configurado?
8. Conclusão
SSRF continua sendo uma das vulnerabilidades mais perigosas em aplicações modernas, especialmente em ambientes cloud. A prevenção eficaz exige uma abordagem em camadas: validação rigorosa de entrada, isolamento de rede, configuração segura de infraestrutura e monitoramento constante. Como desenvolvedor, sua responsabilidade é garantir que o servidor nunca faça requisições não autorizadas — mesmo que indiretamente. Lembre-se: a confiança no servidor é a principal arma do atacante.
Referências
- OWASP SSRF — Documentação oficial da OWASP sobre SSRF, com exemplos e técnicas de ataque
- PortSwigger Web Security Academy - SSRF — Tutorial interativo completo sobre SSRF, incluindo laboratórios práticos
- AWS Security Best Practices for IMDSv2 — Documentação oficial AWS sobre proteção de metadados com IMDSv2
- CWE-918: Server-Side Request Forgery (SSRF) — Entrada oficial do MITRE sobre a classificação CWE-918
- HackerOne SSRF Guide — Guia prático da HackerOne com casos reais e técnicas de exploração
- SSRFmap - Automated SSRF Tool — Ferramenta open-source para teste automatizado de SSRF
- Google Cloud - Protecting against SSRF attacks — Boletim de segurança do Google Cloud sobre proteção contra SSRF