Cross-Site Request Forgery (CSRF)
Cross-Site Request Forgery is a web security vulnerability that tricks authenticated users into executing unwanted actions on a web application where they are currently logged in. By exploiting the trust a website has in the user's browser, attackers can perform state-changing operations without the user's knowledge or consent.
What Is CSRF?
Cross-Site Request Forgery (CSRF or XSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they are currently authenticated. The vulnerability occurs when web applications rely solely on authentication credentials that are automatically included with requests—such as session cookies, basic authentication credentials, or IP addresses—without implementing additional verification mechanisms to ensure the request was intentionally initiated by the legitimate user.
The attack works by exploiting the trust relationship between a user's browser and a web application. When a user is authenticated to a website, their browser automatically attaches authentication credentials to every subsequent request to that domain, regardless of which page or domain initiated the request. An attacker can craft malicious HTML or JavaScript on their own website that, when visited by an authenticated user, triggers requests to the vulnerable application. Since the browser automatically includes authentication cookies, the application cannot distinguish between legitimate user-initiated requests and forged ones.
CSRF attacks are particularly dangerous because they can be executed without any user interaction beyond visiting a malicious page. Unlike phishing attacks that require users to enter credentials, CSRF leverages existing authenticated sessions. The vulnerability has been recognized as a critical security flaw and consistently appears in the OWASP Top 10 list of web application security risks, highlighting its prevalence and potential impact on modern web applications.
How It Works
The victim logs into a legitimate web application (for example, a banking site, email service, or social media platform) using their credentials. Upon successful authentication, the application establishes a session and stores a session identifier in the user's browser as a cookie.
The attacker creates a specially crafted HTTP request that triggers a sensitive action on the vulnerable application—such as changing the user's email address, transferring funds, or modifying account settings. This malicious request is embedded in HTML on an attacker-controlled website, often hidden in an invisible image tag, auto-submitting form, or JavaScript code.
While still authenticated to the vulnerable application, the victim visits the attacker's malicious website. This could happen through a phishing email, clicking a link on a forum, or visiting a compromised legitimate website. The victim does not need to take any explicit action beyond loading the page.
The malicious HTML or JavaScript on the attacker's page causes the victim's browser to automatically send the crafted request to the vulnerable application. Critically, the browser automatically includes the victim's authentication cookies with this request, as it does for all legitimate requests to that domain.
The vulnerable application receives the request with valid authentication credentials and cannot distinguish it from a legitimate user-initiated action. Without proper CSRF protection, the application processes the request, executing the attacker's desired action as if the victim had intentionally performed it themselves.
Vulnerable Code Example
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
// VULNERABLE: No CSRF token verification
// An attacker can change any logged-in user's email
// by tricking them into visiting a malicious page
@PostMapping("/update-email")
public ResponseEntity<?> updateEmail(
@RequestBody EmailUpdateRequest req,
@AuthenticationPrincipal User currentUser
) {
userService.updateEmail(currentUser.getId(), req.getNewEmail());
return ResponseEntity.ok(
Map.of("message", "Email updated successfully")
);
}
}
// Attacker's malicious HTML page:
// <html>
// <body>
// <script>
// fetch('https://vulnerable-app.com/api/user/update-email', {
// method: 'POST',
// credentials: 'include',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify({ newEmail: 'attacker@evil.com' })
// });
// </script>
// </body>
// </html>
//
// When the victim visits this page while logged in,
// their email is changed to attacker@evil.comSecure Code Example
// 1. Enable CSRF protection in Spring Security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.authorizeHttpRequests(auth -> auth
.anyRequest().authenticated()
);
return http.build();
}
}
// 2. Controller automatically validates CSRF token
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
// SECURE: Spring Security automatically validates CSRF token
// Requests without a valid token are rejected with 403 Forbidden
@PostMapping("/update-email")
public ResponseEntity<?> updateEmail(
@RequestBody EmailUpdateRequest req,
@AuthenticationPrincipal User currentUser
) {
userService.updateEmail(currentUser.getId(), req.getNewEmail());
return ResponseEntity.ok(
Map.of("message", "Email updated successfully")
);
}
}
// 3. Frontend includes CSRF token in requests
// fetch('/api/user/update-email', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// 'X-XSRF-TOKEN': getCsrfTokenFromCookie()
// },
// body: JSON.stringify({ newEmail: 'user@example.com' })
// });
//
// Attacker's malicious page cannot access the CSRF token
// due to Same-Origin Policy, so the attack fails.Types of CSRF
GET-based CSRF
The simplest form of CSRF attack, exploiting endpoints that use GET requests to perform state-changing operations. Attackers can trigger these requests using image tags (<img src="...">), iframes, or simple hyperlinks. This attack is particularly dangerous because it requires minimal user interaction—merely loading a page is sufficient. The attack violates the HTTP specification principle that GET requests should be safe and idempotent. Modern frameworks and security guidelines strongly discourage using GET for operations that modify server state.
POST-based CSRF
A more sophisticated attack targeting POST endpoints by using hidden HTML forms that automatically submit when a malicious page loads. The attacker creates a form with pre-filled values pointing to the vulnerable endpoint and uses JavaScript to trigger automatic submission. This type can include arbitrary POST data, making it suitable for complex attacks like fund transfers or password changes. While slightly more complex than GET-based attacks, POST-based CSRF remains highly effective against applications without proper token validation.
Login CSRF
A specialized attack where the attacker forces the victim to log into the vulnerable application using the attacker's credentials. This reverses the typical CSRF scenario—instead of performing actions as the victim, the victim unknowingly uses the attacker's account. The victim might then add sensitive information (credit cards, personal data) to what they believe is their own account, but is actually the attacker's account. This attack can bypass traditional CSRF protections on login forms, as many developers mistakenly believe login endpoints don't require CSRF protection.
Impact
The impact of a successful CSRF attack depends on the privileges of the compromised user and the sensitive actions available in the application. Attacks against regular users can result in unauthorized transactions or data modifications, while attacks against administrative accounts can compromise entire systems.
Attackers can initiate fund transfers, make purchases, or change payment settings without the victim's knowledge. In banking applications, this could result in direct financial loss to victims. E-commerce platforms are vulnerable to unauthorized purchases or gift card redemptions, potentially causing significant financial damage before victims notice the fraudulent activity.
By changing email addresses, passwords, or security questions through CSRF attacks, attackers can permanently take control of user accounts. Once the email is changed, password reset links go to the attacker, locking the legitimate user out of their own account. This is particularly damaging for accounts containing sensitive data or financial information.
Attackers can modify user profiles, settings, or data records without authorization. In administrative interfaces, CSRF can be used to create new admin accounts, modify permissions, or delete critical data. Social media platforms are vulnerable to CSRF attacks that post content on behalf of victims, send messages, or modify privacy settings, potentially causing reputational damage.
CSRF can be combined with other vulnerabilities to amplify impact. Attackers can use CSRF to modify website content management systems, injecting malicious scripts that affect all visitors. In some cases, CSRF has been used to change DNS settings, redirect traffic, or modify firewall rules in router administration panels, compromising entire networks through a single vulnerable user.
Prevention Checklist
Generate unique, unpredictable tokens for each user session (or request) and embed them in forms and AJAX requests. The server validates that the token in the request matches the one associated with the user's session. Modern frameworks like Spring Security, Django, and Rails provide built-in CSRF token generation and validation. This is the most effective defense against CSRF attacks and should be implemented for all state-changing operations.
Configure session cookies with the SameSite attribute set to Strict or Lax to prevent browsers from sending cookies with cross-origin requests. SameSite=Strict provides the strongest protection but may affect legitimate cross-site navigation. SameSite=Lax offers a balance by allowing cookies on top-level GET navigations while blocking them on cross-site POST requests. This provides defense-in-depth alongside CSRF tokens.
Check the Origin and Referer HTTP headers to ensure requests originate from your own domain. While not foolproof (these headers can be missing in some legitimate scenarios), this provides an additional layer of validation. Implement this as a secondary defense mechanism in combination with CSRF tokens, not as a replacement. Be careful to handle missing headers gracefully to avoid breaking legitimate functionality.
For single-page applications and AJAX-heavy websites, require custom HTTP headers (like X-Requested-With: XMLHttpRequest) for all state-changing requests. Browsers prevent cross-origin JavaScript from setting custom headers without triggering a CORS preflight request, making simple CSRF attacks impossible. This pattern is commonly used in REST APIs and modern JavaScript frameworks.
Follow RESTful principles and use POST, PUT, PATCH, or DELETE for operations that modify server state. GET requests should be safe and idempotent—used only for retrieving data without side effects. This prevents simple CSRF attacks using image tags or links, though it doesn't eliminate the need for CSRF protection on POST endpoints. This is a fundamental security best practice that also improves API design.
For critical actions like changing passwords, email addresses, or making large financial transactions, require users to re-enter their password or use multi-factor authentication. This defense-in-depth approach ensures that even if CSRF protection is bypassed, the attacker cannot complete sensitive operations without knowing the user's credentials. This also protects against session hijacking and other session-based attacks.
Real-World Examples
Netflix
A CSRF vulnerability in Netflix allowed attackers to add DVDs to a victim's queue, change their shipping address, and even modify login credentials. The attack could be executed by tricking a logged-in Netflix user into visiting a malicious webpage. This highlighted the importance of CSRF protection even for seemingly low-impact operations, as attackers could chain multiple CSRF requests to fully compromise accounts.
Gmail
Security researcher Petko D. Petkov discovered a CSRF vulnerability in Gmail's filter feature. By tricking users into visiting a specially crafted webpage, attackers could create email filters that forwarded all incoming emails to an attacker-controlled address. This demonstrated how CSRF can be used for sophisticated data exfiltration. Google quickly patched the vulnerability and enhanced their CSRF protections across all services.
ING Direct
The online banking platform ING Direct had a CSRF vulnerability that allowed attackers to initiate money transfers from victims' accounts. The attack exploited the lack of CSRF tokens on the funds transfer page, enabling attackers to craft malicious pages that automatically submitted transfer requests. This incident emphasized the critical need for CSRF protection in financial applications and led to industry-wide security improvements.
WordPress
Multiple CSRF vulnerabilities were discovered in popular WordPress plugins, allowing attackers to perform administrative actions like creating new admin accounts or modifying plugin settings. The vulnerabilities affected millions of WordPress installations worldwide. These incidents demonstrated that CSRF protection must be implemented consistently across all functionality, including third-party plugins and extensions, not just core application features.
Ready to Test Your Knowledge?
Put what you have learned into practice. Try identifying and fixing CSRF vulnerabilities in our interactive coding challenges, or explore more security guides to deepen your understanding.