OWASP CSRF and SSRF
This topic covers two request forgery attacks. CSRF (Cross-Site Request Forgery) tricks a user's browser into sending unauthorized requests on their behalf. SSRF (Server-Side Request Forgery), which is A10 in the OWASP Top 10, tricks the server itself into making requests to internal systems. Both attacks abuse trust relationships — one abuses the trust a server has in a logged-in user's browser, the other abuses the trust internal systems have in the application server.
Part 1: CSRF — Cross-Site Request Forgery
The Signed Blank Check Analogy
You signed a blank check and left it on your desk. A visitor fills in "Pay to: Attacker, Amount: $5,000" and submits it to your bank. The bank sees your authentic signature and processes the payment. You authorized nothing — but the bank cannot tell the difference. CSRF works the same way: the attacker fills in a request using your authenticated browser session.
How CSRF Works
1. Alice is logged into her bank at bank.com
Her browser holds a valid session cookie
2. Alice visits attacker.com (could be any webpage, a forum, an ad)
3. attacker.com contains a hidden form:
<form action="https://bank.com/transfer" method="POST">
<input name="to" value="attacker-account">
<input name="amount" value="5000">
</form>
<script>document.forms[0].submit();</script>
4. Alice's browser automatically submits the form to bank.com
The browser includes Alice's session cookie — it always does
5. bank.com receives the request, sees Alice's valid session
Processes the $5,000 transfer
6. Alice never clicked anything
How to Prevent CSRF
CSRF Tokens: The server generates a unique, secret, unpredictable token and embeds it in every HTML form. When the form is submitted, the server checks that the token is present and correct. An attacker on a different site cannot read this token because of the browser's Same-Origin Policy.
Form with CSRF token:
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="f8a2c9e1b3d7...">
<input name="amount" value="100">
</form>
Attacker's forged form has no valid csrf_token
Server rejects the request
SameSite Cookie Attribute: Setting cookies with SameSite=Strict or SameSite=Lax tells browsers not to include the cookie in cross-site requests. This blocks CSRF at the browser level without requiring token logic.
Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly SameSite=Strict: Cookie never sent on cross-site requests SameSite=Lax: Cookie sent only on top-level navigation GET requests
Part 2: SSRF — Server-Side Request Forgery
The Trusted Messenger Analogy
The CEO's assistant is trusted to send messages anywhere in the building — including the secure vault on the restricted floor. An impersonator tricks the assistant into delivering a message to the vault: "Please send me the contents of this safe." The vault staff trust the assistant's badge, not the content of the message. SSRF exploits that same institutional trust.
How SSRF Works
Many web applications fetch content from URLs provided by users — previewing a link, loading an image from a remote URL, webhooks, or PDF generators that render a given URL. If the server fetches any URL the user specifies without restriction, an attacker provides an internal URL that the server can reach but the attacker cannot.
Normal use — fetch a webpage for preview:
POST /preview
{"url": "https://example.com/news-article"}
Server fetches the article and returns a preview -- intended behavior
SSRF attack — target internal infrastructure:
POST /preview
{"url": "http://169.254.169.254/latest/meta-data/iam/security-credentials/"}
^
AWS EC2 metadata service
Accessible only from within the cloud environment
Returns AWS access keys for the server's IAM role
Server fetches the internal URL, returns the credentials to the attacker
Attacker uses credentials to access all AWS resources the server has permission for
What SSRF Enables
Port scan internal network --> Map systems the attacker cannot reach directly Access cloud metadata APIs --> Steal cloud credentials and keys Reach internal admin panels --> Bypass network perimeter controls Read internal files --> Using file:// protocol if not filtered Attack internal services --> Databases, Elasticsearch, Redis with no auth
How to Prevent SSRF
Allowlist Target Domains: If the fetch feature is meant to reach specific services, only allow those exact domains. Reject everything else.
Allowed: https://trusted-partner.com
Blocked: http://169.254.169.254
http://internal-admin.company.com
file:///etc/passwd
Block Private IP Ranges at the Network Layer: Configure the application server's outbound traffic rules to block requests to private IP address ranges.
Block outbound requests to: 10.0.0.0/8 (private network) 172.16.0.0/12 (private network) 192.168.0.0/16 (private network) 169.254.0.0/16 (link-local, cloud metadata) 127.0.0.0/8 (loopback)
Disable Unnecessary URL-Fetch Features: If a feature that fetches external URLs is not essential, remove it. Every removed feature is a removed attack surface.
CSRF vs SSRF at a Glance
CSRF SSRF
Who is tricked? User's browser The server itself
What is forged? A request from the user A request from the server
Target: The application server Internal / backend systems
Defense: CSRF tokens, SameSite URL allowlists, network blocks
Quick Prevention Checklist
CSRF: [✓] CSRF tokens on all state-changing forms and API calls [✓] SameSite=Strict or Lax on all session cookies [✓] Verify Origin and Referer headers on sensitive endpoints SSRF: [✓] Allowlist permitted external domains for URL-fetch features [✓] Block requests to private IP ranges at the network level [✓] Disable file://, gopher://, and other non-HTTP schemes [✓] Run the app in an environment with restricted outbound access
Key Takeaway
CSRF forges requests from the user's browser; SSRF forges requests from the server. Both are prevented by strict controls on what requests are trusted and where they can go. Never assume a request is safe just because it appears to come from a trusted source.
