November 4, 2026
Updated: November 4, 2026
How SSRF works, blind SSRF, AWS IMDSv1 vs IMDSv2, real cases, OWASP 2025 placement, lab-safe testing and layered prevention.
Mohammed Khalil

Server-side request forgery (SSRF) is a vulnerability in which an attacker makes a server send requests to a destination the attacker chooses. Because the request comes from inside your environment, it can reach internal services, admin panels and cloud metadata endpoints that the attacker could never reach directly. This guide explains how an SSRF attack works, why AWS IMDSv1 made SSRF a credential-theft problem and how IMDSv2 changes that. It also covers what the public record says about the 2019 Capital One breach, blind SSRF, safe testing and the controls that prevent it.
SSRF definition: Server-side request forgery is a flaw where an application fetches a URL or address that a user can influence, without restricting where that request may go. The attacker cannot reach the target directly, so they borrow the server's network position, identity and trust to reach internal or protected systems for them.
MITRE catalogs the weakness as CWE-918: Server-Side Request Forgery. The core problem is not "a bad URL." It is a server that makes outbound requests on a user's behalf without a firm rule about which destinations are allowed.
SSRF usually hides in ordinary features that fetch something from a URL:
Any of these features is safe when it can only reach the destinations it was built for. It becomes SSRF when the destination is open-ended.
The names are similar, and people often confuse them. The difference is whose request is forged and who gets fooled.
| SSRF (server-side request forgery) | CSRF (cross-site request forgery) | |
|---|---|---|
| Who sends the forged request | Your server | The victim's browser |
| Who is tricked | The application's back end | A logged-in user's session |
| What the attacker gains | Access to systems that trust the server's network position or identity | Actions performed with the victim's cookies or session |
| Typical targets | Internal APIs, admin interfaces, databases, cloud metadata services | State-changing actions such as changing an email address or making a transfer |
| Core fix | Restrict outbound destinations; isolate the fetcher | Anti-CSRF tokens, SameSite cookies, origin checks |
An SSRF attack follows the same shape no matter which feature is vulnerable:
url, callback or imageUrl is a common starting point.
The reason SSRF matters so much is the trust boundary. Most networks are built so that the internet cannot reach internal admin tools, databases or metadata services, while application servers can. SSRF turns the application server into a relay across that boundary.
| Target reached through SSRF | Why the server can reach it | Typical impact |
|---|---|---|
| Loopback services on the same host | Admin or debug interfaces often listen only on localhost | Access to management functions that assume only local callers |
| Internal APIs and microservices | Service-to-service traffic is often unauthenticated inside a VPC | Data reads, unintended actions, lateral movement |
| Databases, caches and search clusters with HTTP interfaces | Bound to private addresses and trusted by network location | Data exposure or modification |
| Cloud instance metadata services | Link-local endpoint reachable from every instance by design | Instance details and, on AWS with IMDSv1 allowed, temporary IAM role credentials |
| Internal network ranges | The server sits on networks the attacker cannot see | Host and port discovery from the server's vantage point |
| Third-party systems | The request appears to come from your IP addresses | Abuse attributed to your organization; bypass of partner IP allowlists |
Impact depends on what the vulnerable server can reach and what those systems trust. An SSRF in an isolated fetcher with no internal routes is a low-severity finding. The same bug on a server with broad network access and an IAM role attached can be critical.
Testers and defenders usually group SSRF by how much feedback the attacker gets:
The vulnerable parameter does not have to be a full URL. Applications that accept a hostname, a path that gets appended to an internal base URL, or a URL embedded inside JSON, XML or a document can all produce SSRF.
Blind SSRF happens when an application can be made to send a back-end request to an attacker-chosen destination, but the response never reaches the attacker. A webhook that fires and reports only "saved" is a typical example.
Because nothing comes back, blind SSRF is confirmed out of band. The tester supplies the address of a server they control and watches it for incoming connections. PortSwigger's Web Security Academy notes that seeing only a DNS lookup, without the follow-up HTTP request, often means the application tried to connect but outbound HTTP was filtered while DNS was allowed. The two signals mean different things, and a good report says which one was observed.
Blind SSRF is usually lower impact than basic SSRF because the attacker cannot read internal responses. It is still worth fixing:
Cloud metadata services are the reason SSRF moved from "medium" to "critical" in many cloud environments.
Every Amazon EC2 instance can query the Instance Metadata Service (IMDS) at the link-local address 169.254.169.254 (and, when enabled on Nitro instances in IPv6 subnets, [fd00:ec2::254]), according to AWS's IMDS documentation. IMDS returns instance details. If an IAM role is attached to the instance, it also delivers the temporary credentials for that role, which AWS calls EC2 Role credentials. Software on the instance uses those credentials to call AWS APIs.
That design assumes only code running on the instance can reach the endpoint. SSRF breaks the assumption, because the vulnerable application is code running on the instance.
IMDSv1 is a request/response method: a plain HTTP GET to the metadata path returns the data. There is no session, token or required header. An SSRF that lets an attacker make the server send a basic GET, which is the most common SSRF capability, is enough to read metadata. On an instance with a role attached, that includes the role's temporary credentials. Whatever that role is allowed to do in AWS, the attacker can now attempt from outside.
IMDSv2 is session-oriented. AWS documents these requirements:
/latest/api/token with a header, X-aws-ec2-metadata-token-ttl-seconds, that sets the token lifetime. The minimum is one second and the maximum is six hours (21,600 seconds).X-aws-ec2-metadata-token header. When tokens are set to required, a request without a valid token receives 401 - Unauthorized.X-Forwarded-For header are rejected, which stops most proxies from obtaining a token on a caller's behalf.When AWS announced the IMDSv2 enhancements on November 19, 2019, it framed them as defense in depth against open web application firewalls, open reverse proxies and SSRF. AWS explained that most open WAFs rarely support PUT requests, and that combining PUT with a session token protects against "the vast majority of SSRF vulnerabilities." It did not claim all of them.
| IMDSv1 | IMDSv2 | |
|---|---|---|
| Request model | Single request and response | Session: PUT for a token, then GET with the token |
| Required HTTP method to start | GET | PUT |
| Required headers | None | TTL header on PUT; token header on every GET |
| Behavior behind a forwarding proxy | Works through many proxies | Token PUT rejected if X-Forwarded-For is present |
| Off-instance token use | No token exists | Token is instance-specific; default PUT response hop limit is 1 |
| Exposure to a basic GET-only SSRF | Metadata and role credentials readable | Blocked; the request has no token |
| Can it be the only version allowed | It can be disabled | Yes: set HttpTokens to required ("IMDSv2 only") |

The most important operational detail is that IMDSv2 only helps when IMDSv1 is turned off. The AWS user guide states that by default an instance can use either IMDSv1 or IMDSv2, or both. The effective setting comes from a precedence chain: launch parameters override account-level defaults, which override the AMI setting. AMIs registered with ImdsSupport set to v2.0 launch instances that require IMDSv2, and AWS notes that Amazon Linux 2023 disables IMDSv1 by default. But a launch template that explicitly sets tokens to optional still produces an instance that accepts IMDSv1.
In other words, an organization can believe it "uses IMDSv2" while many instances still answer IMDSv1 requests. That is why cloud penetration tests check the actual HttpTokens value across the fleet, not the policy document.
IMDSv2 is a strong control, but it is not an SSRF fix:
Other clouds use a different guard: a required static header plus proxy detection. Google Cloud's metadata server denies requests that lack the Metadata-Flavor: Google header and automatically rejects requests that contain X-Forwarded-For. Azure Instance Metadata Service requires the Metadata: true header and rejects requests that contain X-Forwarded-For.
These checks stop SSRF bugs that can only control the URL. They do not stop SSRF bugs that can also set headers. AWS argued in its 2019 post that a PUT-plus-token design is always strictly more effective than requiring only a static header.
The Capital One case is the incident most people associate with SSRF and cloud metadata. It is worth separating what the official record states from what has been reconstructed since.
What the U.S. Department of Justice and the OCC documented:
What the primary record does not say: The DOJ announcements and the OCC order do not use the term "server-side request forgery," and they do not describe the request chain step by step. The widely repeated explanation is that a request through the misconfigured firewall reached the instance metadata service and obtained role credentials, which were then used to read storage. That explanation comes from later technical analysis of the charging documents, not from a court finding. Treat it as a well-supported industry reconstruction.
Why the case still belongs in an SSRF guide: The documented facts match the conditions SSRF defenses exist to break. A server-side component on the network edge could be made to reach resources it should not. Cloud credentials sat behind it, with broad access to stored data. Detection came from an outside tip, not internal alerting. Four months after the arrest, AWS published its IMDSv2 enhancements and explicitly named open firewalls, reverse proxies and SSRF as the threats they address.
CVE-2021-26855, published in the National Vulnerability Database on March 3, 2021, affects on-premises Microsoft Exchange Server. NVD maps it to CWE-918. CISA added it to its Known Exploited Vulnerabilities catalog, and NVD records the KEV addition date as November 3, 2021. It shows that SSRF is not only a cloud problem: in an appliance or server product, an SSRF that reaches back-end components can be the first link in a remote code execution chain.
CVE-2024-21893 is an SSRF in the SAML component of Ivanti Connect Secure (9.x, 22.x), Ivanti Policy Secure (9.x, 22.x) and Ivanti Neurons for ZTA. It allows an attacker to access certain restricted resources without authentication. NVD lists it as published on January 31, 2024, the same day CISA added it to the KEV catalog. It is a reminder that SSRF often sits in authentication and federation code that parses externally supplied data.
CVE-2024-34351 is an SSRF in Next.js Server Actions. If an attacker modifies the Host header, and the app is self-hosted, uses Server Actions and performs a redirect to a relative path starting with /, the attacker may be able to make requests that appear to come from the Next.js server itself. It was fixed in Next.js 14.1.1. Our Next.js security testing guide covers this class of framework-level issue in more depth.
| Case | Date (primary record) | Where the SSRF lived | Lesson |
|---|---|---|---|
| Capital One | Arrest July 29, 2019; OCC penalty August 6, 2020 | Misconfigured web application firewall in AWS (DOJ wording) | Edge components with cloud roles need egress limits, IMDSv2 and least privilege |
| CVE-2021-26855 | NVD published March 3, 2021 | On-premises Exchange Server | SSRF can open a path to remote code execution |
| CVE-2024-21893 | NVD published and KEV added January 31, 2024 | SAML component of a VPN gateway | Federation and auth code is SSRF attack surface |
| CVE-2024-34351 | NVD published May 14, 2024 | Framework handling of Host header and redirects | Trusting request headers to build internal URLs creates SSRF |
In the 2021 edition, SSRF had its own category, A10:2021 Server-Side Request Forgery.
The OWASP Top 10:2025 no longer lists SSRF separately. The introduction states that SSRF "has been rolled into" A01:2025 Broken Access Control. The A01:2025 category page names CWE-918 Server-Side Request Forgery (SSRF) among its notable CWEs and lists 40 mapped CWEs in total. The 2025 tenth slot went to a new category, A10:2025 Mishandling of Exceptional Conditions.
The move does not mean SSRF matters less. It reflects how OWASP now frames the problem: an application lets a user reach a resource they should not reach, which is an access control failure. For testing and reporting, SSRF remains its own weakness, CWE-918, with its own test cases and fixes. Our overview of the most common web vulnerabilities shows where SSRF fits among the other classes testers find most often.
Our OWASP Top 10 2025 guide explains every category in the current list, including A01 Broken Access Control.
SSRF testing has to be careful by design. The whole point of the bug is that the server reaches places it should not, so a careless test can touch production systems, internal services or cloud credentials. Professional testing follows a few rules:
example.com or an endpoint the tester controls.The workflow below is a method, not a payload list.
Testers inventory features and parameters that cause outbound requests: webhook URLs, import and preview features, document renderers, integration settings, and API fields with names like url, uri, callback, redirect, feed, image or host. In white-box work, code review finds the actual sinks, meaning calls to HTTP client libraries, headless browsers, XML parsers and file fetchers that receive user-influenced input.
The tester supplies a harmless public destination and observes what the application does. An illustrative request to a hypothetical link-preview API looks like this:
POST /api/v1/link-preview HTTP/1.1
Host: app.example.test
Content-Type: application/json
{"url": "https://example.com/"}If the response contains the title of the example.com page, the feature fetches content server-side and returns it. That is the precondition for basic SSRF, not proof of a vulnerability. The baseline also shows normal timing, error messages and response sizes, which later comparisons need.
For blind or partial cases, the tester uses an out-of-band interaction server they control. Burp Collaborator is common in commercial testing, and the open-source interactsh project is a self-hostable option. The tester generates a unique, single-use hostname for each test, such as https://<unique-id>.<tester-callback-domain>/, and submits it.
The evidence is what arrives at the callback server:
| Signal at the callback server | What it suggests | Next step |
|---|---|---|
| HTTP request from the application's egress IP | Server-side fetch to arbitrary external hosts confirmed | Record source IP, headers and user agent; assess what else the server can reach |
| DNS lookup only, no HTTP | The server resolved the name, but outbound HTTP may be filtered | Report as partial; check egress rules before rating impact |
| Request from a third-party IP or a link scanner | Something other than the application fetched the URL | Do not report as SSRF without further proof |
| Nothing at all | No outbound fetch, or the fetch is restricted | Check for queued or delayed processing before concluding |
Unique identifiers per test matter. They tie each interaction to one parameter and one timestamp, which avoids false positives from link scanners and caches.
Whether the server can reach internal destinations is the real impact question. Mature programs answer it without touching production internals:
HttpTokens set to required, what hop limit is set and what the attached role can do. The finding then states the realistic impact: "SSRF on an instance that allows IMDSv1, with a role that can read these buckets."Our AWS penetration testing guide explains how this cloud configuration review fits into a wider AWS assessment, including IAM and metadata service checks under AWS's testing policy.
A useful SSRF finding includes the vulnerable parameter, the baseline and callback evidence with timestamps, the egress IP, and what the server could reach. It also needs a realistic impact statement that accounts for IMDS configuration and role permissions, plus specific fixes. After remediation, the same callback test is repeated to confirm that the destination is now refused.
No single control prevents SSRF. The reliable approach is layered: restrict destinations in code, back that up in the network, and limit what a successful request could reach in the cloud. The OWASP SSRF Prevention Cheat Sheet is the best single reference and underpins most of the advice below.

The strongest fix is design. If users choose from a known set of partners, accept an identifier and map it to a URL on the server. If users upload an avatar, accept a file upload instead of an image URL. If a feature only needs a domain name, do not accept a full URL with a scheme, port and path.
When the application only needs to reach known systems, maintain an allowlist of exact hostnames, schemes and ports, and refuse everything else. OWASP's guidance is blunt: deny-lists are bypass-prone, so prefer allowlists. Blocklists of "bad" addresses fail because the same internal destination can be written in many ways.
When users genuinely need to supply arbitrary external URLs, as with customer webhooks, OWASP recommends combining a blocklist of internal and special ranges with a proof-of-ownership step. In that step, the destination must return a token your platform issued before you send it real traffic.
URL parsing is where many SSRF defenses fail. Common pitfalls:
@ (credentials in a URL), backslashes and unusual delimiters are classic sources of disagreement. OWASP's rule is to treat any parser disagreement as a rejection.file: and others. Permit only https (or http where required).The safest pattern is to validate the input into a small set of parts (an allowlisted host, a fixed scheme and port) and construct the outgoing request from those parts. Do not pass the user's original string to the HTTP client.
For features that must accept external destinations, check the resolved IP addresses, not just the hostname, and then connect to an address you validated. The Python sketch below is illustrative, not a drop-in library. It shows the logic: allowlist the host, reject credentials and unexpected ports, resolve every address and refuse anything that is not public.
import ipaddress
import socket
from urllib.parse import urlsplit
ALLOWED_HOSTS = {"api.partner.example", "images.partner.example"}
def validated_target(url: str) -> tuple[str, list[str]]:
parts = urlsplit(url)
if parts.scheme != "https" or parts.hostname not in ALLOWED_HOSTS:
raise ValueError("destination not allowed")
if parts.username or parts.password or parts.port not in (None, 443):
raise ValueError("unexpected URL components")
infos = socket.getaddrinfo(parts.hostname, 443, proto=socket.IPPROTO_TCP)
addresses = sorted({host for _, _, _, _, (host, *_) in infos})
for address in addresses:
ip = ipaddress.ip_address(address)
if ip.version == 6 and ip.ipv4_mapped:
ip = ip.ipv4_mapped
if not ip.is_global:
raise ValueError("destination resolves to a non-public address")
return parts.hostname, addressesThe calling code should then connect to one of the returned addresses, keep the original hostname for the Host header, TLS SNI and certificate validation, set short timeouts and disable redirects. Doing this correctly in every HTTP client is hard, which is why the network controls below matter.
Application checks fail. Network controls catch what they miss:
169.254.169.254) and IPv6 unique-local and link-local ranges.HttpTokens to required on existing instances, set account-level defaults to IMDSv2 only, and use AWS's account-level IMDSv2 enforcement once nothing depends on IMDSv1. For an existing instance, AWS documents a command like this:aws ec2 modify-instance-metadata-options \
--instance-id i-0123456789abcdef0 \
--http-tokens required \
--http-put-response-hop-limit 1ImdsV1Enabled (instances that still allow IMDSv1), MetadataNoToken (IMDSv1 calls being made) and MetadataNoTokenRejected (calls refused after you disable IMDSv1), plus the open-source IMDS Packet Analyzer, according to the AWS IMDSv2 transition guide.ec2:RoleDelivery with a value of 2.0 causes API calls made with role credentials obtained through IMDSv1 to fail. The keys ec2:MetadataHttpTokens, ec2:MetadataHttpPutResponseHopLimit and ec2:MetadataHttpEndpoint can prevent anyone from launching or reconfiguring instances to allow IMDSv1.MetadataNoToken metric down to zero and keep it there.Security testing belongs in the development process too. A secure SDLC adds SSRF to threat models for any feature that fetches remote content and adds tests that prove disallowed destinations are refused.
| Layer | Control | How to verify |
|---|---|---|
| Design | Accept identifiers or uploads instead of URLs where possible | Feature review: list every user-influenced fetch |
| Application | Exact allowlist of host, scheme and port; build the request from validated parts | Unit tests that disallowed hosts, schemes and ports are refused |
| Application | Disable redirects; reject parser disagreement; allow only https | Tests with redirecting and malformed inputs in a lab |
| Resolution | Resolve, validate every address, connect to the validated address | Lab test with a hostname that resolves to a private canary |
| Network | Egress proxy or default-deny outbound rules; metadata and private ranges blocked | Callback test from the app subnet to a non-allowlisted host fails |
| Cloud | HttpTokens required, hop limit 1, account default and enforcement on | ImdsV1Enabled sum is zero; describe-instances shows required |
| Identity | Least-privilege instance roles; ec2:RoleDelivery 2.0 condition | IAM review of each role attached to internet-facing compute |
| Detection | Outbound fetch logging and alerts on private and metadata destinations | Trigger a test event and confirm the alert fires |
SSRF is when an attacker gets your server to make a web request for them. The attacker picks the destination, and the server sends the request from inside your network with its own trust and identity. That lets the attacker reach internal systems, such as admin pages or cloud metadata, that are blocked from the internet.
In SSRF the forged request comes from your server, and the target is internal systems that trust that server. In CSRF the forged request comes from a victim's browser, and the target is actions the logged-in user is allowed to perform. SSRF is fixed by restricting where the server can send requests. CSRF is fixed with anti-CSRF tokens, SameSite cookies and origin checks.
Anything the vulnerable server can reach and that trusts it: localhost admin interfaces, internal APIs, databases and caches with HTTP interfaces, internal network ranges and cloud metadata services. On AWS instances that still allow IMDSv1 and have an IAM role attached, that can include the role's temporary credentials.
Avoid fetching user-supplied URLs where possible. Otherwise, allowlist exact destinations, build the outgoing request from validated parts, disable redirects, validate the resolved IP address you connect to, block internal and metadata ranges at an egress proxy, require IMDSv2, and keep cloud roles least-privileged.
Yes, but not as its own category. SSRF was A10:2021. In the OWASP Top 10:2025 it has been rolled into A01:2025 Broken Access Control, which lists CWE-918 among its mapped weaknesses.
No. IMDSv2 protects the AWS metadata service from most SSRF bugs, because a typical SSRF cannot perform the PUT token handshake, and proxied requests are refused a token. It does not protect internal APIs or other services, and it only helps when IMDSv1 is disabled on the instance.
Blind SSRF is when the server makes the attacker-chosen request but never returns the response. It is detected out of band: the tester supplies a unique address on a server they control and watches for the incoming DNS lookup or HTTP request.
SSRF is easy to introduce and easy to miss. Every new webhook, preview or import feature adds another place where the server fetches something on a user's behalf. The checks that matter are the ones that prove the real impact: which destinations the server can reach, whether the instance still answers IMDSv1, and what the attached role can do.
DeepStrike's web application penetration testing services combine automated discovery with manual testing aligned to the OWASP Top 10. Only vulnerabilities validated through exploitation are reported, with actionable remediation steps. For workloads in AWS, Azure or GCP, our cloud penetration testing services test IAM misconfigurations and privilege escalation paths, and map cloud-native attack techniques to MITRE ATT&CK Cloud, the context that decides whether an SSRF is a nuisance or a breach. To scope a test, contact DeepStrike.
Mohammed Khalil is a Cybersecurity Architect at DeepStrike, specializing in advanced penetration testing and offensive security operations. With certifications including CISSP, OSCP, and OSWE, he has led numerous red team engagements for Fortune 500 companies, focusing on cloud security, application vulnerabilities, and adversary emulation. His work involves dissecting complex attack chains and developing resilient defense strategies for clients in the finance, healthcare, and technology sectors.

Stay secure with DeepStrike penetration testing services. Reach out for a quote or customized technical proposal today
Contact Us