Introduction
Your application allows users to fetch images from URLs for their profiles. Everything works as intended until an attacker submits http://169.254.169.254/latest/meta-data/. Within minutes, they've extracted your AWS IAM credentials from the instance metadata service and are pivoting through your cloud infrastructure.
Server-Side Request Forgery (SSRF) occurs when an application fetches resources from user-controlled URLs without proper validation. Attackers exploit this to make requests from the server's perspective, bypassing firewalls and accessing internal systems that should never be externally reachable. This guide explores SSRF attack patterns, prevention strategies, and why AI-powered penetration testing provides superior detection.
Understanding the Risk
SSRF vulnerabilities arise whenever applications make HTTP requests based on user-supplied URLs. Common attack surfaces include URL parameters, webhooks, file imports, and document converters:
# Vulnerable Flask endpoint
@app.route('/fetch')
def fetch_url():
url = request.args.get('url')
response = requests.get(url) # No validation
return response.contentAn attacker can request internal resources:
GET /fetch?url=http://localhost:8080/admin/users
GET /fetch?url=http://192.168.1.1/internal-api/secrets
GET /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/
Cloud Metadata Attacks
Cloud providers expose instance metadata at well-known IP addresses. In AWS, the metadata service at 169.254.169.254 reveals critical information:
# AWS metadata endpoints attackers target
http://169.254.169.254/latest/meta-data/iam/security-credentials/[role-name]
http://169.254.169.254/latest/user-data
http://169.254.169.254/latest/dynamic/instance-identity/documentThese endpoints expose IAM credentials with permissions to access other AWS services, user data scripts that may contain secrets, and network configuration details. Similar metadata services exist on GCP, Azure, and DigitalOcean.
Protocol Exploitation
SSRF isn't limited to HTTP. Depending on the library used, attackers may access other protocols:
file:///etc/passwd
gopher://internal-redis:6379/_*1%0d%0a$8%0d%0aFLUSHALL%0d%0a
dict://internal-server:11211/stats
Prevention Best Practices
Implement URL Allowlists
The most effective defense is maintaining an allowlist of permitted domains:
from urllib.parse import urlparse
ALLOWED_DOMAINS = {'api.example.com', 'cdn.trusted.com', 'images.partner.net'}
def is_url_allowed(url):
try:
parsed = urlparse(url)
return parsed.netloc in ALLOWED_DOMAINS and parsed.scheme in ('http', 'https')
except Exception:
return False
def fetch_url_safely(url):
if not is_url_allowed(url):
raise ValueError("URL not in allowlist")
return requests.get(url, timeout=10)Block Private IP Ranges
When allowlisting isn't practical, block requests to internal networks:
import ipaddress
import socket
from urllib.parse import urlparse
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'), # Link-local and cloud metadata
ipaddress.ip_network('0.0.0.0/8'),
]
def is_ip_blocked(ip_str):
try:
ip = ipaddress.ip_address(ip_str)
return any(ip in network for network in BLOCKED_NETWORKS)
except ValueError:
return True
def validate_url(url):
parsed = urlparse(url)
if parsed.scheme not in ('http', 'https'):
return False
try:
ip = socket.gethostbyname(parsed.hostname)
except socket.gaierror:
return False
return not is_ip_blocked(ip)Use AWS IMDSv2
AWS Instance Metadata Service v2 requires a session token, providing protection against SSRF:
# IMDSv2 requires a PUT request first - SSRF typically can't do this
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/Enforce IMDSv2 in your infrastructure:
resource "aws_instance" "example" {
metadata_options {
http_endpoint = "enabled"
http_tokens = "required" # Enforces IMDSv2
}
}Validate Response Content
Ensure fetched content matches expected types:
def fetch_image_safely(url):
if not validate_url(url):
raise ValueError("Invalid URL")
response = requests.get(url, timeout=10, stream=True)
content_type = response.headers.get('Content-Type', '')
if not content_type.startswith('image/'):
raise ValueError("Response is not an image")
max_size = 10 * 1024 * 1024 # 10MB
content = response.raw.read(max_size + 1)
if len(content) > max_size:
raise ValueError("Response too large")
return contentNetwork Segmentation
Architect your network so application servers can't reach sensitive internal services. Use security groups or firewall rules to limit egress traffic to only required destinations.
Why Traditional Pentesting Falls Short
SSRF vulnerabilities hide in unexpected places—PDF generators, avatar uploaders, webhook configurations, and API integrations. Manual testers may check obvious URL parameters but miss indirect attack vectors where URLs are embedded in JSON payloads or processed asynchronously.
Testing requires probing multiple internal IP ranges, metadata endpoints, and protocol handlers—systematic work that's difficult to complete thoroughly within time-limited engagements.
How AI-Powered Testing Solves It
RedVeil's AI agents systematically identify SSRF attack surfaces across your application, testing URL parameters, file imports, webhooks, and embedded references. The platform probes for cloud metadata access, internal service discovery, and protocol handler exploitation.
When SSRF vulnerabilities are found, RedVeil demonstrates the impact—showing what internal resources are accessible and providing evidence of successful exploitation. On-demand testing allows teams to validate fixes and test new features that process external URLs.
Conclusion
Server-Side Request Forgery transforms trusted server-side requests into a gateway to internal infrastructure. Cloud metadata attacks make SSRF particularly dangerous, as a single vulnerability can expose credentials with broad permissions.
Effective defense combines URL allowlisting, IP range blocking, cloud metadata protection (IMDSv2), and network segmentation. Each layer reduces the attack surface and limits impact.
AI-powered penetration testing from RedVeil identifies SSRF vulnerabilities across your application, validating that URL handling is secure and internal resources remain protected.
Protect your infrastructure from SSRF attacks—test with RedVeil today.