SSRF vs CSRF: What They Are and How to Fix SSRF
SSRF (Server-Side Request Forgery) tricks your own server into sending requests for an attacker, while CSRF (Cross-Site Request Forgery) tricks a logged-in person's browser into sending a request they never meant to make.
This guide is for owners of WordPress, Shopify-connected, SaaS and custom sites who saw "SSRF" on a scan report and wondered if it is the same thing as CSRF. It is not. You will get plain-English definitions, a side-by-side table, the places SSRF usually hides, and a checklist you can hand to a developer or follow yourself.
What is SSRF in plain English?
Many sites have a feature where the server fetches a web address for you. Examples: "import an image from a URL", "fetch a link preview", "send a webhook" (an automatic message to another site), or "generate a PDF from this page".
SSRF happens when an attacker can control which address the server fetches, and the site does not check it. The request then comes from your server, which sits inside your network and is often trusted by other systems.
Here is a simple example. Your site has this feature:
https://example.com/fetch?url=https://example.org/logo.png
An attacker changes the url value to an internal address, such as:
https://example.com/fetch?url=http://169.254.169.254/latest/meta-data/
The address 169.254.169.254 is the "metadata service" on many cloud servers (AWS, and similar services elsewhere). It is only reachable from the server itself. It can hold details about the server, and sometimes temporary access credentials. If your fetch feature returns that response, the attacker just read it through your site.
Other common targets are http://localhost, private network addresses like 10.x.x.x or 192.168.x.x, and admin panels or databases that are not open to the internet.
OWASP (the Open Worldwide Application Security Project, a respected non-profit) added SSRF as its own category in the OWASP Top 10 2021. That link is a useful historical reference. The 2025 edition of the OWASP Top 10 folded SSRF into A01 Broken Access Control. SSRF is still a distinct class of bug with its own fixes.
What is blind SSRF?
Sometimes the server makes the request but never shows the answer to the attacker. This is called blind SSRF. It is harder to exploit, but it can still let someone probe your internal network or trigger actions on internal services. Scanners often flag it by noticing that your server called out to an address they control.
What is CSRF in plain English?
CSRF is a different trick. The victim is a person who is logged in, not your server.
Imagine you are logged in to your site's admin area. You open a malicious page in another tab. That page quietly sends a request to your site, like "change the admin email". Your browser automatically attaches your login cookie, so your site thinks you asked for it.
The attacker never sees your password. They borrow your logged-in session for one action. OWASP explains the defenses in its CSRF Prevention Cheat Sheet.
SSRF vs CSRF: the differences at a glance
The names look almost the same, but only one letter group changes the whole meaning. "Server-Side" means your server is fooled. "Cross-Site" means a user's browser is fooled.
| SSRF | CSRF | |
|---|---|---|
| Full name | Server-Side Request Forgery | Cross-Site Request Forgery |
| Who gets tricked | Your server | A logged-in user's browser |
| Who sends the forged request | Your server | The user's browser |
| What the attacker needs | A feature that fetches a URL | A victim who is logged in and visits a bad page |
| Typical damage | Reading internal data, reaching private systems, cloud credentials | Unwanted actions as that user (change email, change settings) |
| Main fix | Allowlist of destinations, block internal addresses | CSRF tokens, SameSite cookies |
| Where to look | Import, preview, webhook, PDF and screenshot features | Forms and actions that change data |
A quick memory trick: SSRF attacks the server. CSRF attacks the user. If you are searching "what is SSRF and CSRF" because both showed up in one report, treat them as two separate fixes.
Where SSRF hides on small websites
You do not need a giant app to have this risk. Look for any feature that takes a URL from a visitor, an admin or an API call:
- Profile photo or image "upload from URL".
- Link preview or "unfurl" tools (the little card shown when you paste a link).
- Webhook settings where users enter a callback address.
- RSS or feed importers, and "import products from URL" tools.
- PDF, screenshot or invoice generators that load a web page.
- WordPress plugins that fetch remote files, and XML-RPC pingbacks.
- Any parameter named
url,uri,link,src,callback,destorredirect.
SSRF also affects server-side software you do not write yourself, so plugin and package updates matter. The U.S. government's National Vulnerability Database lists many SSRF flaws found in popular plugins and tools.
How to fix an SSRF vulnerability: a checklist
The strongest approach is layered. No single step is perfect, so do as many as fit your setup. The OWASP SSRF Prevention Cheat Sheet is the reference these steps follow.
- Find every feature that fetches a URL. Search your code and plugin list for the examples above. Remove features you do not use.
- Use an allowlist, not a blocklist. Only allow specific, known hosts. Blocklists of "bad" addresses are easy to bypass with tricks like alternate IP formats or DNS names that point to internal addresses.
- Allow only
httpsand the ports you need. Rejectfile://,gopher://,ftp://and similar. - Turn off or re-check redirects. An allowed site can redirect to an internal address. In Python's
requestslibrary, useallow_redirects=False. - Resolve the hostname, then check the IP. Block loopback (
127.0.0.0/8and::1), private ranges (10.0.0.0/8,172.16.0.0/12,192.168.0.0/16and IPv6fc00::/7), link-local (169.254.0.0/16andfe80::/10),0.0.0.0/8, and the shared address range100.64.0.0/10. Also check IPv4-mapped IPv6 forms like::ffff:127.0.0.1. Connect to the IP you checked, so DNS cannot change between the check and the request. - Never return raw responses to the user. If you must show a preview, show only what you expect (an image, a title) and check the content type.
- Lock down the cloud metadata service. On AWS, require IMDSv2 (the token-based version) with this command, replacing the instance ID:
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-endpoint enabled
Test first. Older software or SDKs that still use IMDSv1 can stop working once tokens are required, so check that your apps and AWS SDKs support IMDSv2 and try it on a non-production instance before enforcing it. Set the hop limit to 2 only if containers on the instance need metadata access. IMDSv2 blocks simple GET-only SSRF, but it is not a substitute for fixing the URL-fetching feature. See the AWS instance metadata documentation for details, including the hop limit setting for containers.
- Restrict outbound traffic. Use your cloud firewall or security groups so the web server can only reach the destinations it needs.
- Give servers least privilege. If an attacker does reach credentials, they should unlock as little as possible.
- Update plugins, themes and packages. Many SSRF bugs are fixed upstream.
A minimal allowlist check in Python looks like this:
from urllib.parse import urlparse
ALLOWED_HOSTS = {"images.example-cdn.com", "api.partner.com"}
def is_allowed(url: str) -> bool:
parsed = urlparse(url)
return parsed.scheme == "https" and parsed.hostname in ALLOWED_HOSTS
This is a starting point, not a full fix. Pair it with the IP check in step 5 and with redirects disabled.
Extra steps for WordPress owners
- Update WordPress core and every plugin. Remove plugins you do not use.
- If you do not use pingbacks, turn them off under Settings > Discussion by unticking "Attempt to notify any blogs linked to from the post" and "Allow link notifications from other blogs (pingbacks and trackbacks) on new posts". These settings only affect new posts. They do not disable the XML-RPC
pingback.pingmethod for existing content, so blocking XML-RPC is the stronger control. - If nothing needs XML-RPC (the old remote-publishing interface), ask your host or a security plugin to block it. Check first, because some apps rely on it.
- Ask any plugin developer whether remote fetches use WordPress's safe HTTP functions, such as
wp_safe_remote_get(), which reject unsafe URLs.
How to fix CSRF quickly
Since the two get mixed up, here is the short CSRF checklist:
- Add a CSRF token (a secret, unpredictable value tied to the user's session) to every form and action that changes data. Most frameworks, and WordPress "nonces", already do this.
- Set session cookies with
SameSite=Lax(orStrict), plusSecureandHttpOnly:
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax
- Never change data with a plain GET request.
- Re-ask for the password before sensitive actions like changing an email.
You can also run our security headers checker to see your site's security headers and cookie-related settings.
What if my scanner says "possible SSRF"?
Take it seriously, but do not panic. Automated scanners guess based on patterns. A report can be a real hole, a harmless false alarm, or a blind case where the server made a request and nothing was exposed.
The quickest sanity check is to ask: does this feature accept a URL from a user and fetch it from the server? If not, check other places a server may fetch URLs, such as HTML-to-PDF tools, XML or SVG uploads, and headers like Host or Referer. If none of those apply, it is more likely a false positive. If yes, apply the checklist above.
Only test your own site, and never probe someone else's. Confirming real impact usually takes a human who can read the response, follow the redirects and judge what an attacker could reach. That is exactly where manual versus automated testing differ. For a broader view of your exposure, read is my website hackable. If you suspect something already happened, start at my website was hacked.
Key takeaways
- SSRF fools your server into making requests. CSRF fools a logged-in user's browser. They need different fixes.
- Look for any feature that fetches a URL: imports, previews, webhooks, PDF generators and plugins.
- Fix SSRF with an allowlist, an IP check after DNS lookup, no redirects, and a locked-down cloud metadata service (IMDSv2 on AWS, tested first).
- Fix CSRF with tokens and
SameSitecookies. - A scan flag is a lead, not a verdict. Confirm whether the feature really fetches user-supplied URLs.
Want a human to check?
Start with our free website security check for a no-card, no-login look at your public surface. If you want a person to test your URL-fetching features and write up exact fixes, the Circuit audit is $49 one-time. It is a manual audit of a small site, not an enterprise pentest or a compliance certificate, but it gives you a clear, prioritized list of what to fix.
A real human security engineer audits your whole site by hand and sends a full report: every issue, its severity, and the exact fix. From $49, with a 14-day money-back guarantee.
See pricing