Introduction
Cross-Site Request Forgery (CSRF) is a common web security vulnerability in which an unsuspecting user is tricked into unknowingly performing actions they did not intend to.
A CSRF attack is like a trickster convincing someone to do something they wouldn't normally do.
A classic example of a Cross-Site Request Forgery (CSRF) attack is a hacker slipping a malicious link into your email, hoping you will click it without realizing the danger. When you do, your browser might unknowingly send a request to a website you are already logged into, carrying out actions like making unauthorized purchases, transfers, withdrawals, or changing your password.
Types of CSRF attacks
Client-Side Attacks: These attacks exploit vulnerabilities on the client side. They often involve injecting malicious scripts that alter the DOM, change styles or pictures, or even add external forms to other applications
Server-Side Attacks: These attacks target vulnerabilities on the server side of an application. They involve exploiting weak authentication mechanisms, insecure session management, or other vulnerabilities to forge requests for authenticated users.
Client Side CSRF Prevention Measure
While server-side measures are generally considered the most effective way to prevent Cross-Site Request Forgery (CSRF), implementing client-side restrictions can provide an additional layer of defense.
CAPTCHA (Completely Automated Public Turing Test to Tell Computers and Humans Apart): While CAPTCHA
can be a frustrating experience, it's a valuable tool in the fight against Cross-Site Request Forgery (CSRF). By requiring users to complete a simple task difficult for bots to mimic, CAPTCHA helps verify that a human is behind the request, making it harder for attackers to exploit vulnerable client-side applications.
Content Security Policy (CSP): Integrating a content security policy (CSP) is one of the effective ways to prevent CSRF attacks, cross-site scripting (XSS), and injection attacks on the client side. It acts like a digital shield, strictly controlling which resources your application can load. By using directives like script-src
and style-src
. You can specify where styles and scripts load up from.
<head>
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'nonce-random-string'; style-src 'self' 'nonce-random-string'; img-src 'self' https://yourdomain.com">
</head>
<meta http-equiv="Content-Security-Policy" content="...">
This is the specific meta tag that defines the CSP.
http-equiv="Content-Security-Policy"
This attribute specifies that the meta tag defines the content security policy for the page.
content="..."
This attribute holds the CSP directive, usually a string of semicolon-separated rules.
default-src 'self'
This directive sets the default source for all resources (scripts, stylesheets, images, etc.) to be 'self'
only. This means resources can only be loaded from the same domain as the current webpage.
script-src
This directive specifically defines allowed sources for scripts.
(a) 'self'
Allows scripts from the same domain as the webpage.
(b) 'nonce-XYZ'
Allows scripts with a "nonce" attribute set to the unique value "XYZ"
usually generated on the server.
style-src
Similar to scripts, this directive defines allowed sources for stylesheets
(a) 'self'
Allows stylesheets from the same domain as the webpage.
(b) 'nonce-ABC'
Allows stylesheets with a "nonce" attribute set to the unique value "ABC"
usually generated on the server.
img-src
This directive defines allowed sources for images.
(a) 'self'
Allows images from the same domain as the webpage.
(b) https://yourdomain.com
Allows images from a specific external domain, ensuring it uses a secure HTTPS connection.
In Next.js 13 and later, adding a list of remote patterns for images or other documents in the next.config
file under the hood adds an img-src directive using the domains added.
# typical next.config file specifying allowed sources for images
const nextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "google.com",
},
{
protocol: "https",
hostname: "avatar.vercel.sh",
},
{
protocol: "https",
hostname: "lh3.googleusercontent.com",
},
{
protocol: "https",
hostname: "avatars.githubusercontent.com",
},
],
},
}
3. Input validation: Hackers can send malicious scripts and contents through form inputs that aren't adequately validated and sanitized. Validating inputs is another preventive measure to consider when safeguarding your client-side application from CSRF attacks.
4. HTTP Strict Transport Security (HSTS): Enforcing strict HTTPS connections can help prevent CSRF attacks, but this would only be able to prevent attacks that rely on HTTP.
Server-Side CSRF Prevention Measure
CORS (cross-origin resource sharing): CORS is a mechanism that allows a client-side application to make requests to the server-side application on a different domain. It's also a crucial security measure for preventing CSRF attacks.
Synchronizer Token Pattern (STP): The Synchronizer Token Pattern, or STP for short, is like a secret handshake between your web server and your users' browsers. When a user signs in or starts a new session, it generates and stores a CSRF token in the server sessions, and on forms. The token is sent back to the server on each user request for verification. However, as your user grows, this could lead to potential memory issues if not configured properly. It is also one of the measures to prevent CSRF attacks on the server side.
Double Submit Cookie: The Double Submit Cookie pattern is another measure to consider against preventing CSRF attacks on the server side. It works by storing a CSRF token in cookies and including the same token in a hidden field, preferably inside a form. When the server receives a form submission, it validates the submission by checking if the CSRF token in cookies matches the token stored in the hidden field. This helps to ensure that the form submission originated from the user's browser and not from an attacker.
Checking the HTTP Referer Header: Checking the HTTP referer header is like showing a store clerk your ID to prove you are of age. This helps prevent underage purchases. Similarly, on the server, this involves checking the referer header to verify that a request is coming from a legitimate source. This simple security measure can help prevent Cross-Site Request Forgery (CSRF) attacks.
Conclusion
While these measures can help prevent CSRF attacks, it is important to remember that the digital landscape is constantly evolving. Other threats, like XSS attacks, also pose significant risks. As developers, our responsibility extends beyond creating functional products to ensuring their security. By diligently implementing defenses against CSRF and other attacks, we can safeguard our users' data and protect our businesses from potential harm.
Check out your application CSP status using the links below: