SSRF — Accessing Internal Services Through the Server
Server-Side Request Forgery (SSRF) occurs when an application accepts a user-controlled URL and makes an HTTP request to it from the server itself. The attacker uses the server as a proxy to reach internal networks that are otherwise inaccessible.
Basic Scenario
Legitimate feature: "Fetch URL preview for sharing"
Parameter: POST /preview?url=https://news.example.com/article
Exploitation: POST /preview?url=http://192.168.1.1/admin
The server makes the request internally and returns the response to the attacker.
SSRF in Cloud Environments — Metadata Endpoint
In AWS, every server has access to the instance metadata endpoint:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
A successful SSRF against this endpoint leaks the temporary IAM credentials of the role attached to the instance — full AWS account compromise.
Attack:
POST /fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/prod-role
Response:
{
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"Token": "..."
}
GCP and Azure have similar endpoints.
Bypassing Naive Validations
// String-based blocklist — easily bypassed
Blocked: http://localhost/
Bypass: http://0.0.0.0/
Bypass: http://[::1]/
Bypass: http://127.0.0.1.nip.io/ (resolves to 127.0.0.1)
Bypass: http://0177.0.0.1/ (octal)
Bypass: http://2130706433/ (decimal)
Protocols Beyond HTTP
file:///etc/passwd — reads local file
gopher://internal:25/... — interacts with internal SMTP
dict://internal:6379/ — accesses passwordless Redis
Prevention
1. Host/IP Allowlist
ALLOWED_HOSTS = {'api.partner.com', 'cdn.example.com'}
from urllib.parse import urlparse
parsed = urlparse(user_url)
if parsed.hostname not in ALLOWED_HOSTS:
raise ValueError("Host not permitted")
2. Block Private Ranges After DNS Resolution
import socket, ipaddress
ip = socket.gethostbyname(hostname)
addr = ipaddress.ip_address(ip)
if addr.is_private or addr.is_loopback or addr.is_link_local:
raise ValueError("Private address not permitted")
3. Network Segmentation
Application servers should not have direct access to the internal admin network. Egress firewall blocking 169.254.169.254 and 10.0.0.0/8 from the application process.
4. IMDSv2 on AWS
aws ec2 modify-instance-metadata-options \
--http-tokens required \
--instance-id i-xxxx
IMDSv2 requires a token header — a simple SSRF request can no longer fetch credentials.
5. Least Privilege
IAM Roles with minimal permissions limit damage if credentials are exposed.