What is Cross Site Request Forgery (CSRF)

Last Updated : 19 Sep, 2025

Cross-Site Request Forgery (CSRF) is a critical web vulnerability that allows attackers to trick authenticated users into performing unintended actions, such as changing account details or even taking full control of their accounts.

Web applications typically rely on cookies to maintain user sessions, since HTTP is a stateless protocol and does not natively support persistent authentication. Without cookies, users would need to re-enter their credentials for every request, which would severely impact usability. Cookies solve this by storing session information, but they also make applications susceptible to CSRF attacks if not properly protected.

file

Imagine you’re logged into your online banking account to check your balance. Meanwhile, a malicious website silently tricks your browser into making unauthorized transactions on your behalf. This illustrates a Cross-Site Request Forgery (CSRF) attack, a serious web security vulnerability that impacts countless websites. Recognizing this threat is vital for both users and developers to build safer online experiences.

Conditions Required for a CSRF Attack

For a CSRF attack to succeed all three of the following must hold:

A Relevant Action: The application exposes an action the attacker wants to trigger, for example:

  • Changing a user’s email or password
  • Transferring money
  • Modifying account permissions

Cookie-Based Session Handling

  • The app identifies users solely by a session cookie (or another credential the browser automatically includes).
  • The browser automatically sends that credential with requests made from other sites.
  • No additional server-side verification (e.g., CSRF tokens, same-site cookie policy, or re-authentication) is enforced.

Predictable Request Parameters

  • The attacker can determine or guess all parameters required to perform the action.
  • If a request requires a secret or random value (e.g., the current password, one-time token, or unpredictable nonce), the CSRF attempt will fail.

Exploit in Action

An attacker could create a malicious web page like this:

HTML
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>GFG BANK</title>
  <style>
    body { font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; background:#f2f6fb; margin:0; padding:0; display:flex; align-items:center; justify-content:center; height:100vh; }
    .card { background:#fff; border-radius:12px; box-shadow:0 6px 24px rgba(20,30,50,0.08); width:360px; padding:28px; }
    .brand { display:flex; align-items:center; gap:10px; margin-bottom:18px; }
    .logo { width:40px; height:40px; border-radius:8px; background:linear-gradient(135deg,#0066ff,#00a3ff); }
    h1 { font-size:18px; margin:0; }
    p.note { color:#b23; font-weight:600; margin:12px 0; font-size:13px; }
    label { font-size:13px; color:#334155; display:block; margin-top:12px; }
    input[type="text"], input[type="password"] { width:100%; padding:10px 12px; margin-top:6px; border:1px solid #e6eef9; border-radius:8px; background:#fbfdff; box-sizing:border-box; }
    .actions { display:flex; justify-content:space-between; align-items:center; margin-top:18px; }
    button { background:#0066ff; color:white; border:none; padding:10px 14px; border-radius:8px; cursor:pointer; }
    .ghost { background:transparent; border:1px solid #e6eef9; color:#334155; padding:8px 12px; border-radius:8px; cursor:pointer; }
    .disclaimer { font-size:12px; color:#667085; margin-top:14px; line-height:1.3; }
    footer { margin-top:16px; text-align:center; font-size:12px; color:#9aa4b2; }
  </style>
</head>
<body>
  <div class="card" role="main" aria-labelledby="title">
    <div class="brand">
      <div class="logo" aria-hidden="true"></div>
      <div>
        <h1 id="title">GFG Bank</h1>
      </div>
    </div>
    <form id="demoForm" onsubmit="return handleDemo(event)" autocomplete="off" novalidate>
      <label for="user">Username or email</label>
      <input id="user" name="user" type="text" placeholder="Input Username" required />

      <label for="pass">Password</label>
      <input id="pass" name="pass" type="password" placeholder="••••••••" required />

      <div class="actions">
        <button type="submit">Sign in</button>
        <button type="button" class="ghost" onclick="resetForm()">Reset</button>
      </div>
    </form>

    <footer>
      <div>GFG BANK</div>
    </footer>
  </div>

  <script>
    function sanitize(s){ return String(s).replace(/[<>]/g,''); }

    function handleDemo(e){
      e.preventDefault();
      const user = sanitize(document.getElementById('user').value);
      const pass = sanitize(document.getElementById('pass').value);

      if(!user || !pass){
        alert('Please fill both fields (demo).');
        return false;
      }

      // Demo behaviour: show a local-only modal and clear inputs.
      alert('DEMO: Credentials captured locally (not sent).\\nUsername: ' + user + '\\nPassword length: ' + pass.length);
      resetForm();
      return false;
    }

    function resetForm(){
      document.getElementById('demoForm').reset();
    }
  </script>
</body>
</html>
  1. The hidden form is automatically submitted.
  2. The victim’s browser includes their valid session cookie in the request.
  3. The vulnerable site thinks the user requested the change and updates the email to the attacker’s choice.

Example Scenrio

Below are real-world-inspired CSRF examples

Example 1: GET-based state change (vulnerable endpoint + image tag)

When an application performs a state-changing action on an HTTP GET request (bad practice), an attacker can trigger that action via image/script tags that the browser will load automatically and the browser will include cookies with those requests.

Vulnerable endpoint:

GET /vote?post=123&up=1

Step-by-step attack flow

  1. Victim is logged in to forum.example.
  2. forum.example has a vulnerable endpoint GET /vote?post=123&up=1 that records votes (state change via GET).
  3. Attacker inserts <img src="https://forum.example/vote?post=123&up=1"> on a page or email.
  4. Victim opens the page/email; browser requests the image URL with cookies: vote is recorded.

Sanitised attacker snippet

<img src="https://forum.example/vote?post=123&up=1" alt="">

GET must never change server state; use safe HTTP methods (POST/PUT/DELETE) plus CSRF protections.

Single-page apps (SPAs) that use cookie-based sessions are vulnerable if their APIs accept state-changing requests authenticated only by cookies and lack CSRF defenses.

Step-by-step attack flow

  1. User logs in: The person signs into example.com. The website gives their browser a small file called a session cookie to remember that they’re logged in.
  2. Attacker’s trick page: The attacker makes a web page that secretly sends a request like:
    fetch("https://api.example.com/user/delete-account", { method: "POST", credentials: "include" });
    This code tells the browser: “Send a request to delete the user’s account, and include any cookies you already have.”
  3. Browser sends the cookie: The browser automatically adds the saved session cookie to the request, because it belongs to the same site (api.example.com).
  4. Account deleted (if no protection): If the API doesn’t have CSRF protection, it sees the request as valid and deletes the account even though the user never clicked “Delete” themselves.

Hands On of CSRF

Given below the step by step hands on lab of CSRF

Step 1: Set DVWA security to LOW

Login to DVWA as admin and in the DVWA Security page set the level to Low. This makes the CSRF protection minimal or absent for learning.

file

Step 2: Find the vulnerable action and inspect the request

  • In DVWA, open the CSRF vulnerability page that lets you perform a state change.
  • Perform the action once normally (fill form and submit). In Network you’ll see the request to the target endpoint. Click it and note: Request method (POST or GET), Request URL, or Form field names and values (e.g., New Password, Confirm New Password)
file
  • Note the URL
http://127.0.0.1/dvwa/vulnerabilty/csrf?password_new=password1&password_conf=password1&Change=Change#

Step 3: Create a simple attacker page (csrf.html)

  • On your machine create a file csrf.html containing a form that mimics the DVWA request. Replace the URL and field names with the ones you saw in step 2.
HTML
<html>
<head> 
<title>CSRF Login
</title>
</head>
<body> 
<script>
document.location="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password
_new=password1&password_conf=password1&Change=Change#"";
</script>

</body>
</html> 
  • Save the file in the server page
file

Step 4: Simulate the victim and trigger the attack

  • In one browser (victim): log into DVWA as the victim account and keep that session open.
file
  • In another browser (attacker page): visit http://localhost/csrf.html.
file
  • Because the victim’s browser has an active session cookie for DVWA, when the attacker page auto-submits the form, the browser sends the request including the victim’s cookies to DVWA. If DVWA accepts that request (security LOW), the state change happens (e.g., password resets to the attacker-supplied value).

Step 5: Verify the effect

  • Return to the DVWA login page and try to log in using the newly set password (the one the attacker page used). If it logs in, the CSRF succeeded.
  • Alternatively, check the DVWA user page for changed fields.

Attack Surfaces

CSRF attacks usually target HTTP requests that change something about a user’s account, like their name, email, password, or even logging them in/out without permission.

Exploitation

  • The victim is logged into example.com (session stored in cookies).
  • The attacker hosts a page on evil.com.
  • On that page, the attacker places hidden code that looks like a normal request to example.com (e.g., “change password”).
  • When the victim visits evil.com, the hidden form is automatically submitted.
  • The browser includes the victim’s cookies, so example.com thinks the request is genuine and changes the password to whatever the attacker set.

Prevention

On User Side: User side prevention is very inefficient in terms of browsing experience, prevention can be done by browsing only a single tab at a time and not using the "remember-me" functionality.

On Server Side: There are many proposed ways to implement CSRF protection on server side, among which the use of CSRF tokens is most popular. A CSRF token is a string that is tied to a user's session but is not submitted automatically. A website proceeds only when it receives a valid CSRF token along with the cookies, since there is no way for an attacker to know a user specific token, the attacker can not perform actions on user's behalf.

Comment

Explore